commit 2d8062183f5adbf97a0039c031c08ffa8f1b9d16 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat Apr 6 14:58:08 2024 +0000 Deployed 4786ddd with MkDocs version: 1.5.3 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..26f7e60 --- /dev/null +++ b/404.html @@ -0,0 +1,587 @@ + + + + + + + + + + + + + + + + + + + Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/CONTRIBUTING.html b/CONTRIBUTING.html new file mode 100644 index 0000000..2db3c34 --- /dev/null +++ b/CONTRIBUTING.html @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + CONTRIBUTING - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

CONTRIBUTING

+ +

We welcome contributions!

+

Guidelines

+
    +
  • Small and focused PRs. Please don't include changes that don't address the subject of your PR.
  • +
  • Follow the style of importing functions directly e.g. from os.path import abspath.
  • +
  • Check out the core values of Piku.
  • +
  • PEP8.
  • +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/DESIGN.html b/DESIGN.html new file mode 100644 index 0000000..876879b --- /dev/null +++ b/DESIGN.html @@ -0,0 +1,888 @@ + + + + + + + + + + + + + + + + + + + + + + + Design Notes - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Design Notes

+

The idea behind piku is that it provides the simplest possible way to deploy web apps or services. Simplicity comes at the expense of features, of course, and this document tries to capture the trade-offs.

+

Why uWSGI

+

Using uWSGI in emperor mode gives us the following features for free:

+
    +
  • Painless Python WSGI and virtualenv integration
  • +
  • Process monitoring, restarting, basic resource limiting, etc.
  • +
  • Basic security scaffolding, beginning with the ability to define uid/gid on a per-app basis (if necessary)
  • +
+

Application packaging

+

An app is simply a git repository with some additional files on the top level, the most important of which is the Procfile.

+

Procfile format

+

piku recognizes six kinds of process declarations in the Procfile:

+
    +
  • wsgi workers, in the format dotted.module:entry_point (Python-only)
  • +
  • web workers, which can be anything that honors the PORT environment variable
  • +
  • static workers, which simply mount the first argument as the root static path
  • +
  • preflight which is a special "worker" that is run once before the app is deployed and installing deps (can be useful for cleanups).
  • +
  • release which is a special worker that is run once when the app is deployed, after installing deps (can be useful for build steps).
  • +
  • cron workers, which require a simplified cron expression preceding the command to be run (e.g. cron: */5 * * * * python batch.py to run a batch every 5 minutes)
  • +
  • worker processes, which are standalone workers and can have arbitrary names
  • +
+

So a Python application could have a Procfile like such:

+
# A module to be loaded by uwsgi to serve HTTP requests
+wsgi: module.submodule:app
+# A background worker
+worker: python long_running_script.py
+# Another worker with a different name
+fetcher: python fetcher.py
+# Simple cron expression: minute [0-59], hour [0-23], day [0-31], month [1-12], weekday [1-7] (starting Monday, no ranges allowed on any field)
+cron: 0 0 * * * python midnight_cleanup.py
+release: python initial_cleanup.py
+
+

...whereas a generic app would be:

+
web: embedded_server --port $PORT
+worker: background_worker
+
+

Any worker will be automatically respawned upon failure (uWSGI will automatically shun/throttle crashy workers).

+

ENV settings

+

Since piku is targeted at 12 Factor apps, it allows you to set environment variables in a number of ways, the simplest of which is by adding an ENV file to your repository:

+
SETTING1=foo
+# piku supports comments and variable expansion
+SETTING2=${SETTING1}/bar
+# if this isn't defined, piku will assign a random TCP port
+PORT=9080
+
+

See ENV.md for a full list of Piku variables which can also be set.

+

Environment variables can be changed after deployment using config:set.

+

Runtime detection

+

piku follows a very simple set of rules to determine what kind of runtime is required:

+
    +
  1. If there's a requirements.txt file at the top level, then the app is assumed to require Python.
  2. +
  3. TODO: Go
  4. +
  5. TODO: Node
  6. +
  7. TODO: Java
  8. +
  9. For all the rest, a Procfile is required to determine application entry points.
  10. +
+

Application isolation

+

Application isolation can be tackled at several levels, the most relevant of which being:

+
    +
  • OS/process isolation
  • +
  • Runtime/library isolation
  • +
+

For 1.0, all applications run under the same uid, under separate branches of the same filesystem, and without any resource limiting.

+

Ways to improve upon that (short of full containerisation) typically entail the use of a chroot jail environment (which is available under most POSIX systems in one form or another) or Linux kernel namespaces - both of which are supported by uWSGI (which can also handle resource limiting to a degree).

+

As to runtime isolation, piku only provides virtualenv support until 1.0. Python apps can run under Python 2 or 3 depending on the setting of PYTHON_VERSION, but will always use pre-installed interpreters (Go, Node and Java support will share these limitations in each major version).

+

Internals

+

piku uses two git repositories for each app: a bare repository for client push, and a clone for deployment (which is efficient in terms of storage since git tries to use hardlinks on local clones whenever possible).

+

This separation makes it easier to cope with long/large deployments and restore apps to a pristine condition, since the app will only go live after the deployment clone is reset (via git checkout -f).

+

Components

+

This diagram (available as a dot file in the img folder) outlines how its components interact:

+

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/ENV.html b/ENV.html new file mode 100644 index 0000000..4746f39 --- /dev/null +++ b/ENV.html @@ -0,0 +1,922 @@ + + + + + + + + + + + + + + + + + + + + + + + Configuring Piku via ENV - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Configuring Piku via ENV

+

You can configure deployment settings by placing special variables in an ENV file deployed with your app.

+

Runtime Settings

+
    +
  • PIKU_AUTO_RESTART (boolean, defaults to true): Piku will restart all workers every time the app is deployed. You can set it to 0/false if you prefer to deploy first and then restart your workers separately.
  • +
+

Python

+
    +
  • PYTHON_VERSION (int): Forces Python 3
  • +
+

Node

+
    +
  • NODE_VERSION: installs a particular version of node for your app if nodeenv is found on the path. Optional; if not specified, the system-wide node package is used.
  • +
+
+

NOTE: you will need to stop and re-deploy the app to change the node version in a running app.

+
+

Network Settings

+
    +
  • BIND_ADDRESS: IP address to which your app will bind (typically 127.0.0.1)
  • +
  • PORT: TCP port for your app to listen in (if deploying your own web listener).
  • +
  • DISABLE_IPV6 (boolean): if set to true, it will remove IPv6-specific items from the nginx config, which will accept only IPv4 connections
  • +
+

uWSGI Settings

+
    +
  • UWSGI_MAX_REQUESTS (integer): set the max-requests option to determine how many requests a worker will receive before it's recycled.
  • +
  • UWSGI_LISTEN (integer): set the listen queue size.
  • +
  • UWSGI_PROCESSES (integer): set the processes count.
  • +
  • UWSGI_ENABLE_THREADS (boolean): set the enable-threads option.
  • +
  • UWSGI_LOG_MAXSIZE (integer): set the log-maxsize.
  • +
  • UWSGI_LOG_X_FORWARDED_FOR (boolean): set the log-x-forwarded-for option.
  • +
  • UWSGI_GEVENT: enable the Python 2 gevent plugin
  • +
  • UWSGI_ASYNCIO (integer): enable the Python 2/3 asyncio plugin and set the number of tasks
  • +
  • UWSGI_INCLUDE_FILE: a uwsgi config file in the app's dir to include - useful for including custom uwsgi directives.
  • +
  • UWSGI_IDLE (integer): set the cheap, idle and die-on-idle options to have workers spawned on demand and killed after n seconds of inactivity.
  • +
+
+

NOTE: UWSGI_IDLE applies to all the workers, so if you have UWSGI_PROCESSES set to 4, they will all be killed simultaneously. Support for progressive scaling of workers via cheaper and similar uWSGI configurations will be added in the future.

+
+

nginx Settings

+
    +
  • NGINX_SERVER_NAME: set the virtual host name associated with your app
  • +
  • NGINX_STATIC_PATHS (string, comma separated list): set an array of /url:path values that will be served directly by nginx
  • +
  • NGINX_CLOUDFLARE_ACL (boolean, defaults to false): activate an ACL allowing access only from Cloudflare IPs
  • +
  • NGINX_HTTPS_ONLY (boolean, defaults to false): tell nginx to auto-redirect non-SSL traffic to SSL site.
  • +
+
+

NOTE: if used with Cloudflare, NGINX_HTTPS_ONLY will cause an infinite redirect loop - keep it set to false, use NGINX_CLOUDFLARE_ACL instead and add a Cloudflare Page Rule to "Always Use HTTPS" for your server (use domain.name/* to match all URLs).

+
+

nginx Caching

+

When NGINX_CACHE_PREFIXES is set, nginx will cache requests for those URL prefixes to the running application (uwsgi-like or web workers) and reply on its own for NGINX_CACHE_TIME to the outside. This is meant to be used for compute-intensive operations like resizing images or providing large chunks of data that change infrequently (like a sitemap).

+

The behavior of the cache can be controlled with the following variables:

+
    +
  • NGINX_CACHE_PREFIXES (string, comma separated list): set an array of /url values that will be cached by nginx
  • +
  • NGINX_CACHE_SIZE (integer, defaults to 1): set the maximum size of the nginx cache, in GB
  • +
  • NGINX_CACHE_TIME (integer, defaults to 3600): set the amount of time (in seconds) that valid backend replies (200 304) will be cached.
  • +
  • NGINX_CACHE_REDIRECTS (integer, defaults to 3600): set the amount of time (in seconds) that backend redirects (301 307) will be cached.
  • +
  • NGINX_CACHE_ANY (integer, defaults to 3600): set the amount of time (in seconds) that any other replies (other than errors) will be cached.
  • +
  • NGINX_CACHE_CONTROL (integer, defaults to 3600): set the amount of time (in seconds) for cache control headers (Cache-Control "public, max-age=3600")
  • +
  • NGINX_CACHE_EXPIRY (integer, defaults to 86400): set the amount of time (in seconds) that cache entries will be kept on disk.
  • +
  • NGINX_CACHE_PATH (string, detaults to ~piku/.piku/<appname>/cache): location for the nginx cache data.
  • +
+
+

NOTE: NGINX_CACHE_PATH will be completely managed by nginx and cannot be removed by Piku when the application is destroyed. This is because nginx sets the ownership for the cache to be exclusive to itself, and the piku user cannot remove that file tree. So you will either need to clean it up manually after destroying the app or store it in a temporary filesystem (or set the piku user to the same UID as www-data, which is not recommended).

+
+

Right now, there is no provision for cache revalidation (i.e., nginx asking your backend if the cache entries are still valid), since that requires active application logic that varies depending on the runtime--nginx will only ask your backend for new content when NGINX_CACHE_TIME elapses. If you require that kind of behavior, that is still possible via NGINX_INCLUDE_FILE.

+

Also, keep in mind that using nginx caching with a static website worker will not work (and there's no point to it either).

+

nginx Overrides

+
    +
  • NGINX_INCLUDE_FILE: a file in the app's dir to include in nginx config server section - useful for including custom nginx directives.
  • +
  • NGINX_ALLOW_GIT_FOLDERS: (boolean) allow access to .git folders (default: false, blocked)
  • +
+

Acme Settings

+
    +
  • ACME_ROOT_CA: set the certificate authority that Acme should use to generate public ssl certificates (string, default: letsencrypt.org)
  • +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/FAQ.html b/FAQ.html new file mode 100644 index 0000000..99ee4fc --- /dev/null +++ b/FAQ.html @@ -0,0 +1,632 @@ + + + + + + + + + + + + + + + + + + + + + + + FAQ - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

FAQ

+

Q: Why piku?

+

A: Partly because it's supposed to run on a Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because I know the name will annoy some of my friends.

+

Q: Why Python/why not Go?

+

A: I actually thought about doing this in Go right off the bat, but click is so cool and I needed to have uWSGI running anyway, so I caved in. But I'm very likely to take something like suture and port this across, doing away with uWSGI altogether.

+

Go also (at the time) did not have a way to vendor dependencies that I was comfortable with, and that is also why Go support fell behind. Hopefully that will change soon.

+

Q: Does it run under Python 3?

+

A: Right now, it only runs on Python 3, even though it can deploy apps written in both major versions. It began its development using 2.7 and usingclick for abstracting the simpler stuff, and I eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since I wanted to make installing it on the Raspberry Pi as simple as possible.

+

Q: Why not just use dokku?

+

A: I used dokku daily for most of my personal stuff for a good while. But it relied on a number of x64 containers that needed to be completely rebuilt for ARM, and when I decided I needed something like this (March 2016) that was barely possible - docker itself was not fully baked for ARM yet, and people were at the time trying to get herokuish and buildstep to build on ARM.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL-centos-9.html b/INSTALL-centos-9.html new file mode 100644 index 0000000..a9e8f4d --- /dev/null +++ b/INSTALL-centos-9.html @@ -0,0 +1,827 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation on CentOS 9 - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + +

Installation on CentOS 9

+
+

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

+
+

All steps done as root (or add sudo if you prefer).

+

Dependencies

+

Before installing piku, you need to install the following packages:

+
dnf in -y ansible-core ansible-collection-ansible-posix ansible-collection-ansible-utils nginx nodejs npm openssl postgresql postgresql-server postgresql-contrib python3 python3-pip uwsgi uwsgi-logger-file uwsgi-logger-systemd
+pip install click
+
+

Set up the piku user

+
adduser --groups nginx piku
+# copy & setup piku.py
+su - piku -c "wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup"
+
+

Set up SSH access

+

See INSTALL.md

+

uWSGI Configuration

+

FYI The uWSGI Emperor – multi-app deployment

+
mv /home/piku/.piku/uwsgi/uwsgi.ini /etc/uwsgi.d/piku.ini # linking alone increases the host attack service if one can get inside the piku user or one of its apps, so moving is safer
+chown piku:piku /etc/uwsgi.d/piku.ini # In Tyrant mode (set by default in /etc/uwsgi.ini) the Emperor will run the vassal using the UID/GID of the vassal configuration file
+systemctl restart uwsgi
+journalctl -feu uwsgi # see logs
+
+

nginx Configuration

+

FYI Setting up and configuring NGINX

+
echo "include /home/piku/.piku/nginx/*.conf;" > /etc/nginx/conf.d/piku.conf
+systemctl restart nginx
+journalctl -feu nginx # see logs
+
+

Set up systemd.path to reload nginx upon config changes

+
# Set up systemd.path to reload nginx upon config changes
+su -
+git clone https://github.com/piku/piku.git # need a copy of some files
+cp -v piku/piku-nginx.{path,service} /etc/systemd/system/
+systemctl enable piku-nginx.{path,service}
+systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `active: active (waiting)`
+
+

Notes

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL-other.html b/INSTALL-other.html new file mode 100644 index 0000000..6ccf524 --- /dev/null +++ b/INSTALL-other.html @@ -0,0 +1,1123 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation on other platforms - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + +

Installation on other platforms

+
+

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

+
+

Dependencies

+

Before running piku for the first time, you need to install the following Python packages at the system level:

+

Raspbian Jessie, Debian 8, Ubuntu 16.04

+
sudo apt-get install git python3-virtualenv python3-pip
+sudo pip3 install -U click
+
+

Raspbian Wheezy

+
sudo apt-get install git python3
+sudo easy_install3 -U pip3
+sudo pip3 install -U click virtualenv
+
+

These may or may not be installed already (click usually isn't). For Raspbian Wheezy this is the preferred approach, since current apt packages are fairly outdated.

+

Set up the piku user, Set up SSH access

+

See INSTALL.md

+

uWSGI Installation (Debian Linux variants, any architecture)

+

uWSGI can be installed in a variety of fashions. These instructions cover both pre-packaged and source installs depending on your system.

+

Raspbian Jessie, Debian 8

+
+

Warning

+

These OS releases are no longer supported and these instructions are kept for reference purposes only.

+
+

In Raspbian Jessie, Debian 8 and other systemd distributions where uWSGI is already available pre-compiled (but split into a number of plugins), do the following:

+

# At the time of this writing, this installs uwsgi 2.0.7 on Raspbian Jessie.
+# You can also install uwsgi-plugins-all if you want to get runtime support for other languages
+sudo apt-get install uwsgi uwsgi-plugin-python3
+# refer to our executable using a link, in case there are more versions installed
+sudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku
+# disable the standard uwsgi startup script
+sudo systemctl disable uwsgi
+
+# add our own startup script
+sudo cp /tmp/uwsgi-piku.service /etc/systemd/system/
+sudo systemctl enable uwsgi-piku
+sudo systemctl start uwsgi-piku
+
+# check it's running
+sudo systemctl status uwsgi-piku.service
+
+Important Note: Make sure you run piku.py setup as outlined above before starting the service.

+

Also, please note that uwsgi-piku.service, as provided, creates a /run/uwsgi-piku directory for it to place socket files and sundry. This is not actually used at the moment, since the uwsgi socket file is placed inside the piku user directory for consistency across OS distributions. This will be cleaned up in a later release.

+

Raspbian Wheezy

+
+

Warning

+

This OS release is no longer supported and these instructions are kept for reference purposes only.

+
+

Since Raspbian Wheezy is a fairly old distribution by now, its uwsgi-* packages are completely outdated (and depend on Python 2.6), so we have to compile and install our own version, as well as using an old-style init script to have it start automatically upon boot.

+

sudo apt-get install build-essential python-dev libpcre3-dev
+# At the time of this writing, this installs 2.0.12
+sudo pip install uwsgi
+# refer to our executable using a link, in case there are more versions installed
+sudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku
+
+# set up our init script
+sudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku
+sudo chmod +x /etc/init.d/uwsgi-piku
+sudo update-rc.d uwsgi-piku defaults
+sudo service uwsgi-piku start
+
+Important Note: Make sure you run python3 piku.py setup as outlined above before starting the service.

+

Ubuntu 14.04 LTS

+
+

Warning

+

This OS release is no longer supported and these instructions are kept for reference purposes only.

+
+

This is a mix of both the above, and should change soon when we get 16.04. If you have trouble, install uWSGI via pip instead.

+
# At the time of this writing, this installs uwsgi 1.9.17 on Ubuntu 14.04 LTS.
+# You can also install uwsgi-plugins-all if you want to get runtime support for other languages
+sudo apt-get install uwsgi uwsgi-plugin-python3
+# refer to our executable using a link, in case there are more versions installed
+sudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku
+
+# set up our init script
+sudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku
+sudo chmod +x /etc/init.d/uwsgi-piku
+sudo update-rc.d uwsgi-piku defaults
+sudo service uwsgi-piku start
+
+

nginx Installation (Raspbian 8, Ubuntu 16.04)

+
+

Warning

+

These OS releases are no longer supported and these instructions are kept for reference purposes only.

+
+

PLEASE NOTE: There is a bug in nginx 1.6.2 under Raspbian 8 that causes it to try to allocate around a gigabyte of RAM when using SSL with SPDY. I seriously recommend using Ubuntu instead, if you can, or disabling SSL altogether.

+
sudo apt-get install nginx
+# Set up nginx to pick up our config files
+sudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default
+# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `Active: active (waiting)`
+# Restart NGINX
+sudo systemctl restart nginx
+
+

Java 8 Installation (All Debian Linux variants, on Raspberry Pi)

+
+

Warning

+

OpenJDK 8 is no longer shipping with most distributions and these instructions are kept for reference purposes only.

+
+

To be able to deploy Java apps, we're going to need to install Java (and, since we're going to be doing so on ARM, it's best to use Oracle's runtime). To do that, we're going to use the webupd8team PPA, which has a (cross-platform) Java installer.

+

First, get rid of OpenJDK and import the PPA key:

+
sudo apt-get remove openjdk*
+sudo apt-key adv --recv-key --keyserver keyserver.ubuntu.com EEA14886
+
+

Raspbian Jessie

+
+

Warning

+

This OS release is no longer supported and these instructions are kept for reference purposes only.

+
+

For Jessie, we're going to use the trusty version of the installer:

+
sudo tee /etc/apt/sources.list.d/webupd8team.list
+deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main 
+deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main
+^D
+
+

Ubuntu 16.04 for ARM

+
+

Warning

+

This OS release is no longer supported and these instructions are kept for reference purposes only.

+
+

For Xenial, we're going to use its own version:

+
sudo tee /etc/apt/sources.list.d/webupd8team.list
+deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main 
+deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main
+^D
+
+

Now perform the actual install:

+
sudo apt-get update
+sudo apt-get install oracle-java8-installer oracle-java8-set-default
+
+

Go Installation (All Debian Linux variants, on Raspberry Pi)

+
+

This is EXPERIMENTAL and may not work at all.

+
+

Raspbian Wheezy/Jessie

+
+

Warning

+

Wheezy and Jessie are no longer supported and these instructions are kept for reference purposes only.

+
+

Since Raspbian's Go compiler is version 1.0.2, we need something more up-to-date.

+
    +
  1. Get an ARM 6 binary tarball
  2. +
  3. Unpack it under the piku user like such:
  4. +
+
sudo su - piku
+tar -zxvf /tmp/go1.5.3.linux-arm.tar.gz
+# remove unnecessary files
+rm -rf go/api go/blog go/doc go/misc go/test
+
+
    +
  1. Give it a temporary GOPATH and install godep:
  2. +
+
sudo su - piku
+GOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get github.com/tools/godep
+# temporary workaround until this is fixed in godep or Go 1.7(?)
+GOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get golang.org/x/sys/unix
+
+

TODO: complete this.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL-raspbian-9.4-stretch-10-buster.html b/INSTALL-raspbian-9.4-stretch-10-buster.html new file mode 100644 index 0000000..d32d383 --- /dev/null +++ b/INSTALL-raspbian-9.4-stretch-10-buster.html @@ -0,0 +1,851 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation on Raspbian Stretch or Buster - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + +

Installation on Raspbian Stretch or Buster

+
+

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

+
+

piku setup is simplified in modern Debian versions, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. However, Stretch still ships with Python 3.5, which means it's not an ideal environment for new deployments on both Intel and ARM devices (Buster, in turn, ships with Python 3.7).

+

Setting up your Raspberry Pi

+

Download and install Raspbian onto an SD card.

+

After you install it is recommended that you do the following to update your installation to the latest available software.

+
# update apt-get
+sudo apt-get update
+
+# upgrade all software
+sudo apt-get upgrade
+
+

Configure your installation. It is recommended that Change Password from the default and setup Locale Options (Locale and Timezone) and EXPAND FILESYSTEM. You will also want to Enable SSH. +

# configure your installation
+sudo raspi-config
+

+

At this point it is a good idea to sudo shutdown -h now and make a backup image of the card.

+

Dependencies

+

Before installing piku, you need to install the following packages:

+
sudo apt-get install -y build-essential certbot git \
+    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \
+    python-certbot-nginx python-dev python-pip python-virtualenv \
+    python3-dev python3-pip python3-click python3-virtualenv \
+    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \
+    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python \
+    uwsgi-plugin-lua5.1 uwsgi-plugin-lua5.2 uwsgi-plugin-luajit
+
+

Set up the piku user, Set up SSH access

+

See INSTALL.md

+

uWSGI Configuration

+

uWSGI in Stretch and Buster requires very little configuration, since it is already properly packaged. All you need to do is create a symlink to the piku configuration file in /etc/uwsgi/apps-enabled:

+
sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini
+sudo systemctl restart uwsgi
+
+

nginx Configuration

+

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

+
server {
+    listen 80 default_server;
+    listen [::]:80 default_server;
+    root /var/www/html;
+    index index.html index.htm;
+    server_name _;
+    location / {
+        try_files $uri $uri/ =404;
+    }
+}
+# replace `PAAS_USERNAME` with the username you created.
+include /home/PAAS_USERNAME/.piku/nginx/*.conf;
+
+

Set up systemd.path to reload nginx upon config changes

+
# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `Active: active (waiting)`
+# Restart NGINX
+sudo systemctl restart nginx
+
+

Notes

+
+

This file was last updated on June 2019

+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL-ubuntu-18.04-bionic.html b/INSTALL-ubuntu-18.04-bionic.html new file mode 100644 index 0000000..71e67a8 --- /dev/null +++ b/INSTALL-ubuntu-18.04-bionic.html @@ -0,0 +1,819 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation on Ubuntu 18.04 LTS (Bionic) - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + +

Installation on Ubuntu 18.04 LTS (Bionic)

+
+

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

+
+

piku setup is simplified in Bionic, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Bionic also ships with Python 3.6, this is an ideal environment for new deployments on both Intel and ARM devices.

+

Dependencies

+

Before installing piku, you need to install the following packages:

+
sudo apt-get update
+sudo apt-get install -y build-essential certbot git \
+    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \
+    python-certbot-nginx python-dev python-pip python-virtualenv \
+    python3-dev python3-pip python3-click python3-virtualenv \
+    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \
+    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python
+
+

Set up the piku user, Set up SSH access

+

See INSTALL.md

+

uWSGI Configuration

+

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

+
sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini
+sudo systemctl restart uwsgi
+
+

nginx Configuration

+

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

+
server {
+    listen 80 default_server;
+    listen [::]:80 default_server;
+    root /var/www/html;
+    index index.html index.htm;
+    server_name _;
+    location / {
+        try_files $uri $uri/ =404;
+    }
+}
+# replace `PAAS_USERNAME` with the username you created.
+include /home/PAAS_USERNAME/.piku/nginx/*.conf;
+
+

Set up systemd.path to reload nginx upon config changes

+
# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `Active: active (waiting)`
+# Restart NGINX
+sudo systemctl restart nginx
+
+

Notes

+
+

This file was last updated on November 2018

+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL-ubuntu-22.04-jammy.html b/INSTALL-ubuntu-22.04-jammy.html new file mode 100644 index 0000000..f1bd65a --- /dev/null +++ b/INSTALL-ubuntu-22.04-jammy.html @@ -0,0 +1,819 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation on Ubuntu 22.04 LTS (Jammy) - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + +

Installation on Ubuntu 22.04 LTS (Jammy)

+
+

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

+
+

piku setup is simplified in Jammy, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Jammy also ships with Python 3.10, this is an ideal environment for new deployments on both Intel and ARM devices.

+

Dependencies

+

Before installing piku, you need to install the following packages:

+
sudo apt-get update
+sudo apt-get install -y build-essential certbot git \
+    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \
+    python3-certbot-nginx \
+    python3-dev python3-pip python3-click python3-virtualenv \
+    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python3 \
+    uwsgi-plugin-python3 uwsgi-plugin-tornado-python3
+
+

Set up the piku user, Set up SSH access

+

See INSTALL.md

+

uWSGI Configuration

+

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

+
sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini
+sudo systemctl restart uwsgi
+
+

nginx Configuration

+

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

+
server {
+    listen 80 default_server;
+    listen [::]:80 default_server;
+    root /var/www/html;
+    index index.html index.htm;
+    server_name _;
+    location / {
+        try_files $uri $uri/ =404;
+    }
+}
+# replace `PAAS_USERNAME` with the username you created.
+include /home/PAAS_USERNAME/.piku/nginx/*.conf;
+
+

Set up systemd.path to reload nginx upon config changes

+
# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `Active: active (waiting)`
+# Restart NGINX
+sudo systemctl restart nginx
+
+

Notes

+
+

This file was last updated on November 2018

+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/INSTALL.html b/INSTALL.html new file mode 100644 index 0000000..73eb679 --- /dev/null +++ b/INSTALL.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + + + + + + + + + + + Installation - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Installation

+

piku requires Python 3, uWSGI, SSH, and a Linux distribution that runs systemd, such as Raspbian Jessie/Debian 8+/Ubuntu/Fedora/CentOS.

+

There are 3 ways to install piku on a server:

+
    +
  1. +

    Manually: Follow INSTALL-x.md for which ever platform. If you are running piku on specific Linux versions, feel free to contribute your own instructions.

    +
  2. +
  3. +

    Use cloud-init to do it automatically at VPS build time: https://github.com/piku/cloud-init

    +
  4. +
  5. +

    Use piku-bootstrap to do it once your box is already provisioned: https://github.com/piku/piku-bootstrap

    +
  6. +
+

Generic steps (referenced from INSTALL-x)

+

Set up the piku user

+

piku requires a separate user account to run. To create a new user with the right group membership (we're using the built-in www-data group because it's generally thought of as a less-privileged group), enter the following command:

+
# pick a username
+export PAAS_USERNAME=piku
+# create it
+sudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data $PAAS_USERNAME
+# copy & setup piku.py
+sudo su - $PAAS_USERNAME -c "wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup"
+
+

The setup output should be something like this:

+
Creating '/home/piku/.piku/apps'.
+Creating '/home/piku/.piku/repos'.
+Creating '/home/piku/.piku/envs'.
+Creating '/home/piku/.piku/uwsgi'.
+Creating '/home/piku/.piku/uwsgi-available'.
+Creating '/home/piku/.piku/uwsgi-enabled'.
+Creating '/home/piku/.piku/logs'.
+Setting '/home/piku/piku.py' as executable.
+
+

Set up SSH access

+

If you don't have an SSH public key (or never used one before), you need to create one. The following instructions assume you're running some form of UNIX on your own machine (Windows users should check the documentation for their SSH client, unless you have Cygwin installed).

+

On your own machine, issue the ssh-keygen command and follow the prompts:

+
ssh-keygen 
+
+Generating public/private rsa key pair.
+Enter file in which to save the key (/home/youruser/.ssh/id_rsa): 
+Created directory '/home/youruser/.ssh'.
+Enter passphrase (empty for no passphrase): 
+Enter same passphrase again: 
+Your identification has been saved in /home/youruser/.ssh/id_rsa.
+Your public key has been saved in /home/youruser/.ssh/id_rsa.pub.
+The key fingerprint is:
+85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff youruser@yourlaptop.lan
+The key's randomart image is:
++--[ RSA 2048]----+
+<...>
++-----------------+
+
+

Copy the resulting id_rsa.pub (or equivalent, just make sure it's the public file) to your piku server and do the following:

+
sudo su - piku
+python3 piku.py setup:ssh /tmp/id_rsa.pub
+
+Adding key '85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff'.
+
+

Now if you look at .ssh/authorized_keys, you should see something like this:

+
sudo su - piku
+cat .ssh/authorized_keys
+
+command="FINGERPRINT=85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff NAME=default /home/piku/piku.py $SSH_ORIGINAL_COMMAND",no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhTYZi/qeJBKgU3naI8FNjQgeMYnMsEtqrOmUc4lJoPNH2qBUTNkzwThGqsBm2HNLPURWMiEifBqF+kRixMud67Co7Zs9ys7pwFXkJB9bbZasd2JCGfVZ4UYXHnvgejSWkLAV/4bObhsbP2vWOmbbm91Cwn+PGJgoiW08yrd45lsDmgv9cUAJS3e8LkgVELvIDg49yM5ArB88oxwMEoUgWU2OniHmH0o1zw5I8WXHRhHOjb8cGsdTYfXEizRKKRTM2Mu6dKRt1GNL0UbWi8iS3uJHGD3AcQ4ApdMl5X0gTixKHponStOrSMy19/ltuIy8Sjr7KKPxz07ikMYr7Vpcp youruser@yourlaptop.lan
+
+

This line is what enables you to SSH (and perform git over SSH operations) to the piku user without a password, verifying your identity via your public key, restricting what can be done remotely and passing on to piku itself the commands you'll be issuing.

+

Test

+

From your machine, do:

+
ssh piku@pi.lan
+
+Usage: piku.py [OPTIONS] COMMAND [ARGS]...
+
+  The smallest PaaS you've ever seen
+
+Options:
+  --help  Show this message and exit.
+
+Commands:
+  apps              List applications
+  config            Show application configuration
+  config:get        Retrieve a configuration setting
+  config:live       Show live configuration settings
+  config:set        Set a configuration setting
+  deploy            Deploy an application
+  destroy           Destroy an application
+  disable           Disable an application
+  enable            Enable an application
+  logs              Tail an application log
+  ps                Show application worker count
+  ps:scale          Show application configuration
+  restart           Restart an application
+  setup             Initialize paths
+  setup:ssh         Set up a new SSH key
+Connection to pi.lan closed.
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/PLUGINS.html b/PLUGINS.html new file mode 100644 index 0000000..0a2b84e --- /dev/null +++ b/PLUGINS.html @@ -0,0 +1,653 @@ + + + + + + + + + + + + + + + + + + + + + + + PLUGINS - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

PLUGINS

+ +

Thanks to jsenin, piku currently has experimental support for external plugins via #129.

+

Plugins are inserted into the commands listing and can perform arbitrary actions. At this moment there are no official plugins, but here is an example file that should be placed at ~/.piku/plugins/postgres/__init__.py that could contain the commands to manage a Postgres database:

+
import click
+
+@click.group()
+def postgres():
+    """Postgres command plugin"""
+    pass
+
+@postgres.command("postgres:create")
+@click.argument('name')
+@click.argument('user')
+@click.argument('password')
+def postgres_create():
+    """Postgres create a database"""
+    pass
+
+@postgres.command("postgres:drop")
+@click.argument('name')
+def postgres_drop():
+    """Postgres drops a database"""
+    pass
+
+@postgres.command("postgres:import")
+@click.argument('name')
+def postgres_drop():
+    """Postgres import a database"""
+    pass
+
+@postgres.command("postgres:dump")
+@click.argument('name')
+def postgres_drop():
+    """Postgres dumps a database SQL"""
+    pass
+
+def cli_commands():
+    return postgres
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/assets/external/fonts.googleapis.com/css.49ea35f2.css b/assets/external/fonts.googleapis.com/css.49ea35f2.css new file mode 100644 index 0000000..8187a64 --- /dev/null +++ b/assets/external/fonts.googleapis.com/css.49ea35f2.css @@ -0,0 +1,594 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 new file mode 100644 index 0000000..943c5a0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 new file mode 100644 index 0000000..2bfc2ce Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 new file mode 100644 index 0000000..b2391b9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 new file mode 100644 index 0000000..a4699c7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 new file mode 100644 index 0000000..bfcc76f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 new file mode 100644 index 0000000..d4ec189 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 new file mode 100644 index 0000000..22c57b0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 new file mode 100644 index 0000000..d2f30b5 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 new file mode 100644 index 0000000..c88b8ae Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 new file mode 100644 index 0000000..6363b1c Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 new file mode 100644 index 0000000..dd5a4a2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 new file mode 100644 index 0000000..6abf54d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 new file mode 100644 index 0000000..c8091bc Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 new file mode 100644 index 0000000..a56a6ed Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 new file mode 100644 index 0000000..508baef Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 new file mode 100644 index 0000000..9213da0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 new file mode 100644 index 0000000..ef920e5 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 new file mode 100644 index 0000000..9a378af Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 new file mode 100644 index 0000000..e1b7a79 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 new file mode 100644 index 0000000..e0d3c43 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 new file mode 100644 index 0000000..dd587a2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 new file mode 100644 index 0000000..9d7fb7f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 new file mode 100644 index 0000000..6068138 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 new file mode 100644 index 0000000..b289f00 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 new file mode 100644 index 0000000..87711c0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 new file mode 100644 index 0000000..0f6e60b Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 new file mode 100644 index 0000000..91231c9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 new file mode 100644 index 0000000..c009987 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 new file mode 100644 index 0000000..1bb7737 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 new file mode 100644 index 0000000..771fbec Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 new file mode 100644 index 0000000..cb9bfa7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 new file mode 100644 index 0000000..a0d68e2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 new file mode 100644 index 0000000..6399552 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 new file mode 100644 index 0000000..94ab5fb Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 new file mode 100644 index 0000000..3c45011 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 new file mode 100644 index 0000000..fc71d94 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 new file mode 100644 index 0000000..020729e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 new file mode 100644 index 0000000..47da362 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 new file mode 100644 index 0000000..22ddee9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 new file mode 100644 index 0000000..8a8de61 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 new file mode 100644 index 0000000..6284d2e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 new file mode 100644 index 0000000..72ce0e9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 new file mode 100644 index 0000000..022274d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 new file mode 100644 index 0000000..48edd1b Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 new file mode 100644 index 0000000..cb41535 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 new file mode 100644 index 0000000..1d988a3 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 new file mode 100644 index 0000000..11e6a46 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 new file mode 100644 index 0000000..50fb8e7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 new file mode 100644 index 0000000..1f1c97f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 new file mode 100644 index 0000000..1623005 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 new file mode 100644 index 0000000..6f232c3 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 new file mode 100644 index 0000000..a3e5aef Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 new file mode 100644 index 0000000..f73f27d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 new file mode 100644 index 0000000..135d06e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 differ diff --git a/assets/external/unpkg.com/iframe-worker/shim.js b/assets/external/unpkg.com/iframe-worker/shim.js new file mode 100644 index 0000000..5f1e232 --- /dev/null +++ b/assets/external/unpkg.com/iframe-worker/shim.js @@ -0,0 +1 @@ +"use strict";(()=>{function c(s,n){parent.postMessage(s,n||"*")}function d(...s){return s.reduce((n,e)=>n.then(()=>new Promise(r=>{let t=document.createElement("script");t.src=e,t.onload=r,document.body.appendChild(t)})),Promise.resolve())}var o=class extends EventTarget{constructor(e){super();this.url=e;this.m=e=>{e.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:e.data})),this.onmessage&&this.onmessage(e))};this.e=(e,r,t,i,m)=>{if(r===`${this.url}`){let a=new ErrorEvent("error",{message:e,filename:r,lineno:t,colno:i,error:m});this.dispatchEvent(a),this.onerror&&this.onerror(a)}};let r=document.createElement("iframe");r.hidden=!0,document.body.appendChild(this.iframe=r),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Setting up a Raspberry Pi Piku Server from Scratch

+

DISCLAIMER!

+

These instructions are correct as of April 1st 2016

+

Start by flashing a SD card with the latest Raspbian Jessie Lite image.

+

Do this in your Raspberry Pi as 'pi' user

+

Boot it, launch raspi-config to perform (at least) the following configuration:

+
# as 'pi' user
+sudo raspi-config
+
+
    +
  • 1) expand filesystem
  • +
  • 2) change default user password
  • +
  • 3) set up memory split as you wish (for a headless server, 16MB for GPU)
  • +
+

Optionally:

+
    +
  • 4) set up over-clocking.
  • +
+

Secure your install

+

Delete the existing SSH keys and recreate them (why? read this).

+
# as 'pi' user
+sudo rm -v /etc/ssh/ssh_host_*
+sudo dpkg-reconfigure openssh-server
+sudo reboot
+
+

This will recreate the server keys. Next, update your system:

+
# as 'pi' user
+sudo apt update
+sudo apt upgrade
+
+

Install required packages

+

As of April 2016, the shipping versions with Raspbian are recent enough to run piku:

+
# as 'pi' user
+sudo apt install -y python-virtualenv python-pip git uwsgi uwsgi-plugin-python nginx
+sudo pip install -U click
+sudo reboot
+
+

Meanwhile, go get the goodies while Raspberry Pi is rebooting

+

(We assume you know about ssh keys and have one "at hand", you'll need to copy it)

+

Clone the piku repo somewhere and copy files to your Raspberry Pi

+
# as yourself in your desktop/laptop computer
+scp piku.py uwsgi-piku.service nginx.default.dist pi@your_machine:/tmp
+scp your_public_ssh_key.pub pi@your_machine:/tmp
+
+

Back to the Pi

+

Prepare uWSGI (part one): +

# as 'pi' user
+sudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku
+sudo systemctl disable uwsgi
+sudo cp /tmp/uwsgi-piku.service /etc/systemd/system/
+sudo systemctl daemon-reload
+sudo systemctl enable uwsgi-piku
+

+

Prepare nginx:

+
sudo apt-get install nginx
+# Set up nginx to pick up our config files
+sudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default
+# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Check the status of piku-nginx.service
+systemctl status piku-nginx.path # should return `Active: active (waiting)`
+# Restart NGINX
+sudo systemctl restart nginx
+
+

Create 'piku' user and set it up

+
# as 'pi' user
+sudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku
+sudo su - piku
+# this is now done as 'piku' user
+mkdir ~/.ssh
+chmod 700 ~/.ssh
+cp /tmp/piku.py ~/piku.py
+python piku.py setup
+python piku.py setup:ssh /tmp/id_rsa.pub
+# return to 'pi' user
+exit
+
+

Prepare uWSGI (part two):

+
# as 'pi' user
+sudo systemctl start uwsgi-piku
+sudo systemctl status uwsgi-piku.service
+
+

If you're still here, odds are your Pi is ready for work

+

Go back to your machine and try these commands:

+
# as yourself in your desktop/laptop computer
+ssh piku@your_machine
+
+Usage: piku.py [OPTIONS] COMMAND [ARGS]...
+
+  The smallest PaaS you've ever seen
+
+Options:
+  --help  Show this message and exit.
+
+Commands:
+  apps              List applications
+  config            Show application configuration
+  config:get        Retrieve a configuration setting
+  config:live       Show live configuration settings
+  config:set        Set a configuration setting
+  deploy            Deploy an application
+  destroy           Destroy an application
+  disable           Disable an application
+  enable            Enable an application
+  logs              Tail an application log
+  ps                Show application worker count
+  ps:scale          Show application configuration
+  restart           Restart an application
+  setup             Initialize paths
+  setup:ssh         Set up a new SSH key
+Connection to your_machine closed.
+
+

If you find any bugs with this quickstart guide, please let Luis Correia know ;)

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/old/ROADMAP.html b/old/ROADMAP.html new file mode 100644 index 0000000..74ac3a9 --- /dev/null +++ b/old/ROADMAP.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + Roadmap - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Roadmap

+

This was the original roadmap, filed here in 2019-11-21 for future reference:

+
    +
  • [ ] Prebuilt Raspbian image with everything baked in
  • +
  • [ ] chroot/namespace isolation (tentative)
  • +
  • [ ] Relay commands to other nodes
  • +
  • [ ] Proxy deployments to other nodes (build on one box, deploy to many)
  • +
  • [ ] Support Clojure/Java deployments through boot or lein
  • +
  • [ ] Sample Go app
  • +
  • [ ] Support Go deployments (in progress)
  • +
  • [ ] nginx SSL optimization/cypher suites, own certificates
  • +
  • [ ] Review deployment messages
  • +
  • [ ] WIP: Review docs/CLI command documentation (short descriptions done, need help <cmd> and better descriptions)
  • +
  • [ ] Lua/WSAPI support
  • +
  • [x] Support for Java Apps with maven/gradle (in progress through jwsgi, by @matrixjnr)
  • +
  • [x] Django and Wisp examples (by @chr15m)
  • +
  • [x] Project logo (by @chr15m)
  • +
  • [x] Various release/deployment improvements (by @chr15m)
  • +
  • [x] Support Node deployments (by @chr15m)
  • +
  • [x] Let's Encrypt support (by @chr15m)
  • +
  • [x] Allow setting nginx IP bindings in ENV file (NGINX_IPV4_ADDRESS and NGINX_IPV6_ADDRESS)
  • +
  • [x] Cleanups to remove 2.7 syntax internally
  • +
  • [x] Change to Python 3 runtime as default, with PYTHON_VERSION = 2 as fallback
  • +
  • [x] Run in Python 3 only
  • +
  • [x] (experimental) REPL in feature/repl
  • +
  • [x] Python 3 support through PYTHON_VERSION = 3
  • +
  • [x] static URL mapping to arbitrary paths (hat tip to @carlosefr for nginx tuning)
  • +
  • [x] remote CLI (requires ssh -t)
  • +
  • [x] saner uWSGI logging
  • +
  • [x] gevent activated when UWSGI_GEVENT = <integer>
  • +
  • [x] enable CloudFlare ACL when NGINX_CLOUDFLARE_ACL = True
  • +
  • [x] Autodetect SPDY/HTTPv2 support and activate it
  • +
  • [x] Basic nginx SSL config with self-signed certificates and UNIX domain socket connection
  • +
  • [x] nginx support - creates an nginx config file if NGINX_SERVER_NAME is defined
  • +
  • [x] Testing with pre-packaged uWSGI versions on Debian Jessie (yes, it was painful)
  • +
  • [x] Support barebones binary deployments
  • +
  • [x] Complete installation instructions (see INSTALL.md, which also has a draft of Go installation steps)
  • +
  • [x] Installation helper/SSH key setup
  • +
  • [x] Worker scaling
  • +
  • [x] Remote CLI commands for changing/viewing applied/live settings
  • +
  • [x] Remote tailing of all logfiles for a single application
  • +
  • [x] HTTP port selection (and per-app environment variables)
  • +
  • [x] Sample Python app
  • +
  • [X] Procfile support (wsgi and worker processes for now, web processes being tested)
  • +
  • [x] Basic CLI commands to manage apps
  • +
  • [x] virtualenv isolation
  • +
  • [x] Support Python deployments
  • +
  • [x] Repo creation upon first push
  • +
  • [x] Basic understanding of how dokku works
  • +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/old/SCRIPTS.html b/old/SCRIPTS.html new file mode 100644 index 0000000..4853a2a --- /dev/null +++ b/old/SCRIPTS.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + + + + + + + + + Ubuntu 16.04 - Piku + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + +

Ubuntu 16.04

+

Full installation sequence on a blank Ubuntu 16.04 machine:

+
sudo apt-get update
+sudo apt-get -y dist-upgrade
+sudo apt-get -y autoremove
+sudo apt-get install -y tmux vim htop fail2ban uwsgi uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python uwsgi-plugin-tornado-python nginx libxml2-dev libxslt1-dev python-dev zlib1g-dev build-essential git python3-virtualenv python3-pip python3-click
+sudo pip3 install -U click pip
+sudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku
+
+# move to /tmp and grab our distribution files
+cd /tmp
+wget https://raw.githubusercontent.com/piku/piku/master/piku.py
+wget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.path
+wget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.service
+wget https://raw.githubusercontent.com/piku/piku/master/nginx.default.dist
+wget https://raw.githubusercontent.com/piku/piku/master/uwsgi-piku.service
+# Set up nginx to pick up our config files
+sudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default
+# Set up systemd.path to reload nginx upon config changes
+sudo cp ./piku-nginx.{path, service} /etc/systemd/system/
+sudo systemctl enable piku-nginx.{path,service}
+sudo systemctl start piku-nginx.path
+# Restart NGINX
+sudo systemctl restart nginx
+sudo cp /tmp/uwsgi-piku.service /etc/systemd/system/
+# refer to our executable using a link, in case there are more versions installed
+sudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku
+# disable the standard uwsgi startup script
+sudo systemctl disable uwsgi
+sudo systemctl enable uwsgi-piku
+sudo su - piku
+mkdir ~/.ssh
+chmod 700 ~/.ssh
+# now copy the piku script to this user account
+cp /tmp/piku.py ~/piku.py
+python3 piku.py setup
+# Now import your SSH key using setup:ssh
+
+sudo systemctl start uwsgi-piku
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.js b/search/search_index.js new file mode 100644 index 0000000..b6bcaef --- /dev/null +++ b/search/search_index.js @@ -0,0 +1 @@ +var __index = {"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"CONTRIBUTING.html","title":"CONTRIBUTING","text":"

We welcome contributions!

"},{"location":"CONTRIBUTING.html#guidelines","title":"Guidelines","text":""},{"location":"DESIGN.html","title":"Design Notes","text":"

The idea behind piku is that it provides the simplest possible way to deploy web apps or services. Simplicity comes at the expense of features, of course, and this document tries to capture the trade-offs.

"},{"location":"DESIGN.html#why-uwsgi","title":"Why uWSGI","text":"

Using uWSGI in emperor mode gives us the following features for free:

"},{"location":"DESIGN.html#application-packaging","title":"Application packaging","text":"

An app is simply a git repository with some additional files on the top level, the most important of which is the Procfile.

"},{"location":"DESIGN.html#procfile-format","title":"Procfile format","text":"

piku recognizes six kinds of process declarations in the Procfile:

So a Python application could have a Procfile like such:

# A module to be loaded by uwsgi to serve HTTP requests\nwsgi: module.submodule:app\n# A background worker\nworker: python long_running_script.py\n# Another worker with a different name\nfetcher: python fetcher.py\n# Simple cron expression: minute [0-59], hour [0-23], day [0-31], month [1-12], weekday [1-7] (starting Monday, no ranges allowed on any field)\ncron: 0 0 * * * python midnight_cleanup.py\nrelease: python initial_cleanup.py\n

...whereas a generic app would be:

web: embedded_server --port $PORT\nworker: background_worker\n

Any worker will be automatically respawned upon failure (uWSGI will automatically shun/throttle crashy workers).

"},{"location":"DESIGN.html#env-settings","title":"ENV settings","text":"

Since piku is targeted at 12 Factor apps, it allows you to set environment variables in a number of ways, the simplest of which is by adding an ENV file to your repository:

SETTING1=foo\n# piku supports comments and variable expansion\nSETTING2=${SETTING1}/bar\n# if this isn't defined, piku will assign a random TCP port\nPORT=9080\n

See ENV.md for a full list of Piku variables which can also be set.

Environment variables can be changed after deployment using config:set.

"},{"location":"DESIGN.html#runtime-detection","title":"Runtime detection","text":"

piku follows a very simple set of rules to determine what kind of runtime is required:

  1. If there's a requirements.txt file at the top level, then the app is assumed to require Python.
  2. TODO: Go
  3. TODO: Node
  4. TODO: Java
  5. For all the rest, a Procfile is required to determine application entry points.
"},{"location":"DESIGN.html#application-isolation","title":"Application isolation","text":"

Application isolation can be tackled at several levels, the most relevant of which being:

For 1.0, all applications run under the same uid, under separate branches of the same filesystem, and without any resource limiting.

Ways to improve upon that (short of full containerisation) typically entail the use of a chroot jail environment (which is available under most POSIX systems in one form or another) or Linux kernel namespaces - both of which are supported by uWSGI (which can also handle resource limiting to a degree).

As to runtime isolation, piku only provides virtualenv support until 1.0. Python apps can run under Python 2 or 3 depending on the setting of PYTHON_VERSION, but will always use pre-installed interpreters (Go, Node and Java support will share these limitations in each major version).

"},{"location":"DESIGN.html#internals","title":"Internals","text":"

piku uses two git repositories for each app: a bare repository for client push, and a clone for deployment (which is efficient in terms of storage since git tries to use hardlinks on local clones whenever possible).

This separation makes it easier to cope with long/large deployments and restore apps to a pristine condition, since the app will only go live after the deployment clone is reset (via git checkout -f).

"},{"location":"DESIGN.html#components","title":"Components","text":"

This diagram (available as a dot file in the img folder) outlines how its components interact:

"},{"location":"ENV.html","title":"Configuring Piku via ENV","text":"

You can configure deployment settings by placing special variables in an ENV file deployed with your app.

"},{"location":"ENV.html#runtime-settings","title":"Runtime Settings","text":""},{"location":"ENV.html#python","title":"Python","text":""},{"location":"ENV.html#node","title":"Node","text":"

NOTE: you will need to stop and re-deploy the app to change the node version in a running app.

"},{"location":"ENV.html#network-settings","title":"Network Settings","text":""},{"location":"ENV.html#uwsgi-settings","title":"uWSGI Settings","text":"

NOTE: UWSGI_IDLE applies to all the workers, so if you have UWSGI_PROCESSES set to 4, they will all be killed simultaneously. Support for progressive scaling of workers via cheaper and similar uWSGI configurations will be added in the future.

"},{"location":"ENV.html#nginx-settings","title":"nginx Settings","text":"

NOTE: if used with Cloudflare, NGINX_HTTPS_ONLY will cause an infinite redirect loop - keep it set to false, use NGINX_CLOUDFLARE_ACL instead and add a Cloudflare Page Rule to \"Always Use HTTPS\" for your server (use domain.name/* to match all URLs).

"},{"location":"ENV.html#nginx-caching","title":"nginx Caching","text":"

When NGINX_CACHE_PREFIXES is set, nginx will cache requests for those URL prefixes to the running application (uwsgi-like or web workers) and reply on its own for NGINX_CACHE_TIME to the outside. This is meant to be used for compute-intensive operations like resizing images or providing large chunks of data that change infrequently (like a sitemap).

The behavior of the cache can be controlled with the following variables:

NOTE: NGINX_CACHE_PATH will be completely managed by nginx and cannot be removed by Piku when the application is destroyed. This is because nginx sets the ownership for the cache to be exclusive to itself, and the piku user cannot remove that file tree. So you will either need to clean it up manually after destroying the app or store it in a temporary filesystem (or set the piku user to the same UID as www-data, which is not recommended).

Right now, there is no provision for cache revalidation (i.e., nginx asking your backend if the cache entries are still valid), since that requires active application logic that varies depending on the runtime--nginx will only ask your backend for new content when NGINX_CACHE_TIME elapses. If you require that kind of behavior, that is still possible via NGINX_INCLUDE_FILE.

Also, keep in mind that using nginx caching with a static website worker will not work (and there's no point to it either).

"},{"location":"ENV.html#nginx-overrides","title":"nginx Overrides","text":""},{"location":"ENV.html#acme-settings","title":"Acme Settings","text":""},{"location":"FAQ.html","title":"FAQ","text":"

Q: Why piku?

A: Partly because it's supposed to run on a Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because I know the name will annoy some of my friends.

Q: Why Python/why not Go?

A: I actually thought about doing this in Go right off the bat, but click is so cool and I needed to have uWSGI running anyway, so I caved in. But I'm very likely to take something like suture and port this across, doing away with uWSGI altogether.

Go also (at the time) did not have a way to vendor dependencies that I was comfortable with, and that is also why Go support fell behind. Hopefully that will change soon.

Q: Does it run under Python 3?

A: Right now, it only runs on Python 3, even though it can deploy apps written in both major versions. It began its development using 2.7 and usingclick for abstracting the simpler stuff, and I eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since I wanted to make installing it on the Raspberry Pi as simple as possible.

Q: Why not just use dokku?

A: I used dokku daily for most of my personal stuff for a good while. But it relied on a number of x64 containers that needed to be completely rebuilt for ARM, and when I decided I needed something like this (March 2016) that was barely possible - docker itself was not fully baked for ARM yet, and people were at the time trying to get herokuish and buildstep to build on ARM.

"},{"location":"INSTALL-centos-9.html","title":"Installation on CentOS 9","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

All steps done as root (or add sudo if you prefer).

"},{"location":"INSTALL-centos-9.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

dnf in -y ansible-core ansible-collection-ansible-posix ansible-collection-ansible-utils nginx nodejs npm openssl postgresql postgresql-server postgresql-contrib python3 python3-pip uwsgi uwsgi-logger-file uwsgi-logger-systemd\npip install click\n
"},{"location":"INSTALL-centos-9.html#set-up-the-piku-user","title":"Set up the piku user","text":"
adduser --groups nginx piku\n# copy & setup piku.py\nsu - piku -c \"wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup\"\n
"},{"location":"INSTALL-centos-9.html#set-up-ssh-access","title":"Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-centos-9.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

FYI The uWSGI Emperor \u2013 multi-app deployment

mv /home/piku/.piku/uwsgi/uwsgi.ini /etc/uwsgi.d/piku.ini # linking alone increases the host attack service if one can get inside the piku user or one of its apps, so moving is safer\nchown piku:piku /etc/uwsgi.d/piku.ini # In Tyrant mode (set by default in /etc/uwsgi.ini) the Emperor will run the vassal using the UID/GID of the vassal configuration file\nsystemctl restart uwsgi\njournalctl -feu uwsgi # see logs\n
"},{"location":"INSTALL-centos-9.html#nginx-configuration","title":"nginx Configuration","text":"

FYI Setting up and configuring NGINX

echo \"include /home/piku/.piku/nginx/*.conf;\" > /etc/nginx/conf.d/piku.conf\nsystemctl restart nginx\njournalctl -feu nginx # see logs\n
"},{"location":"INSTALL-centos-9.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsu -\ngit clone https://github.com/piku/piku.git # need a copy of some files\ncp -v piku/piku-nginx.{path,service} /etc/systemd/system/\nsystemctl enable piku-nginx.{path,service}\nsystemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `active: active (waiting)`\n
"},{"location":"INSTALL-centos-9.html#notes","title":"Notes","text":""},{"location":"INSTALL-other.html","title":"Installation on other platforms","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

"},{"location":"INSTALL-other.html#dependencies","title":"Dependencies","text":"

Before running piku for the first time, you need to install the following Python packages at the system level:

"},{"location":"INSTALL-other.html#raspbian-jessie-debian-8-ubuntu-1604","title":"Raspbian Jessie, Debian 8, Ubuntu 16.04","text":"
sudo apt-get install git python3-virtualenv python3-pip\nsudo pip3 install -U click\n
"},{"location":"INSTALL-other.html#raspbian-wheezy","title":"Raspbian Wheezy","text":"
sudo apt-get install git python3\nsudo easy_install3 -U pip3\nsudo pip3 install -U click virtualenv\n

These may or may not be installed already (click usually isn't). For Raspbian Wheezy this is the preferred approach, since current apt packages are fairly outdated.

"},{"location":"INSTALL-other.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-other.html#uwsgi-installation-debian-linux-variants-any-architecture","title":"uWSGI Installation (Debian Linux variants, any architecture)","text":"

uWSGI can be installed in a variety of fashions. These instructions cover both pre-packaged and source installs depending on your system.

"},{"location":"INSTALL-other.html#raspbian-jessie-debian-8","title":"Raspbian Jessie, Debian 8","text":"

Warning

These OS releases are no longer supported and these instructions are kept for reference purposes only.

In Raspbian Jessie, Debian 8 and other systemd distributions where uWSGI is already available pre-compiled (but split into a number of plugins), do the following:

# At the time of this writing, this installs uwsgi 2.0.7 on Raspbian Jessie.\n# You can also install uwsgi-plugins-all if you want to get runtime support for other languages\nsudo apt-get install uwsgi uwsgi-plugin-python3\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n# disable the standard uwsgi startup script\nsudo systemctl disable uwsgi\n\n# add our own startup script\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\nsudo systemctl enable uwsgi-piku\nsudo systemctl start uwsgi-piku\n\n# check it's running\nsudo systemctl status uwsgi-piku.service\n
Important Note: Make sure you run piku.py setup as outlined above before starting the service.

Also, please note that uwsgi-piku.service, as provided, creates a /run/uwsgi-piku directory for it to place socket files and sundry. This is not actually used at the moment, since the uwsgi socket file is placed inside the piku user directory for consistency across OS distributions. This will be cleaned up in a later release.

"},{"location":"INSTALL-other.html#raspbian-wheezy_1","title":"Raspbian Wheezy","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

Since Raspbian Wheezy is a fairly old distribution by now, its uwsgi-* packages are completely outdated (and depend on Python 2.6), so we have to compile and install our own version, as well as using an old-style init script to have it start automatically upon boot.

sudo apt-get install build-essential python-dev libpcre3-dev\n# At the time of this writing, this installs 2.0.12\nsudo pip install uwsgi\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n\n# set up our init script\nsudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku\nsudo chmod +x /etc/init.d/uwsgi-piku\nsudo update-rc.d uwsgi-piku defaults\nsudo service uwsgi-piku start\n
Important Note: Make sure you run python3 piku.py setup as outlined above before starting the service.

"},{"location":"INSTALL-other.html#ubuntu-1404-lts","title":"Ubuntu 14.04 LTS","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

This is a mix of both the above, and should change soon when we get 16.04. If you have trouble, install uWSGI via pip instead.

# At the time of this writing, this installs uwsgi 1.9.17 on Ubuntu 14.04 LTS.\n# You can also install uwsgi-plugins-all if you want to get runtime support for other languages\nsudo apt-get install uwsgi uwsgi-plugin-python3\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n\n# set up our init script\nsudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku\nsudo chmod +x /etc/init.d/uwsgi-piku\nsudo update-rc.d uwsgi-piku defaults\nsudo service uwsgi-piku start\n
"},{"location":"INSTALL-other.html#nginx-installation-raspbian-8-ubuntu-1604","title":"nginx Installation (Raspbian 8, Ubuntu 16.04)","text":"

Warning

These OS releases are no longer supported and these instructions are kept for reference purposes only.

PLEASE NOTE: There is a bug in nginx 1.6.2 under Raspbian 8 that causes it to try to allocate around a gigabyte of RAM when using SSL with SPDY. I seriously recommend using Ubuntu instead, if you can, or disabling SSL altogether.

sudo apt-get install nginx\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-other.html#java-8-installation-all-debian-linux-variants-on-raspberry-pi","title":"Java 8 Installation (All Debian Linux variants, on Raspberry Pi)","text":"

Warning

OpenJDK 8 is no longer shipping with most distributions and these instructions are kept for reference purposes only.

To be able to deploy Java apps, we're going to need to install Java (and, since we're going to be doing so on ARM, it's best to use Oracle's runtime). To do that, we're going to use the webupd8team PPA, which has a (cross-platform) Java installer.

First, get rid of OpenJDK and import the PPA key:

sudo apt-get remove openjdk*\nsudo apt-key adv --recv-key --keyserver keyserver.ubuntu.com EEA14886\n
"},{"location":"INSTALL-other.html#raspbian-jessie","title":"Raspbian Jessie","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

For Jessie, we're going to use the trusty version of the installer:

sudo tee /etc/apt/sources.list.d/webupd8team.list\ndeb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main \ndeb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main\n^D\n
"},{"location":"INSTALL-other.html#ubuntu-1604-for-arm","title":"Ubuntu 16.04 for ARM","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

For Xenial, we're going to use its own version:

sudo tee /etc/apt/sources.list.d/webupd8team.list\ndeb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main \ndeb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main\n^D\n

Now perform the actual install:

sudo apt-get update\nsudo apt-get install oracle-java8-installer oracle-java8-set-default\n
"},{"location":"INSTALL-other.html#go-installation-all-debian-linux-variants-on-raspberry-pi","title":"Go Installation (All Debian Linux variants, on Raspberry Pi)","text":"

This is EXPERIMENTAL and may not work at all.

"},{"location":"INSTALL-other.html#raspbian-wheezyjessie","title":"Raspbian Wheezy/Jessie","text":"

Warning

Wheezy and Jessie are no longer supported and these instructions are kept for reference purposes only.

Since Raspbian's Go compiler is version 1.0.2, we need something more up-to-date.

  1. Get an ARM 6 binary tarball
  2. Unpack it under the piku user like such:
sudo su - piku\ntar -zxvf /tmp/go1.5.3.linux-arm.tar.gz\n# remove unnecessary files\nrm -rf go/api go/blog go/doc go/misc go/test\n
  1. Give it a temporary GOPATH and install godep:
sudo su - piku\nGOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get github.com/tools/godep\n# temporary workaround until this is fixed in godep or Go 1.7(?)\nGOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get golang.org/x/sys/unix\n

TODO: complete this.

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html","title":"Installation on Raspbian Stretch or Buster","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in modern Debian versions, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. However, Stretch still ships with Python 3.5, which means it's not an ideal environment for new deployments on both Intel and ARM devices (Buster, in turn, ships with Python 3.7).

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#setting-up-your-raspberry-pi","title":"Setting up your Raspberry Pi","text":"

Download and install Raspbian onto an SD card.

After you install it is recommended that you do the following to update your installation to the latest available software.

# update apt-get\nsudo apt-get update\n\n# upgrade all software\nsudo apt-get upgrade\n

Configure your installation. It is recommended that Change Password from the default and setup Locale Options (Locale and Timezone) and EXPAND FILESYSTEM. You will also want to Enable SSH.

# configure your installation\nsudo raspi-config\n

At this point it is a good idea to sudo shutdown -h now and make a backup image of the card.

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python-certbot-nginx python-dev python-pip python-virtualenv \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \\\n    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python \\\n    uwsgi-plugin-lua5.1 uwsgi-plugin-lua5.2 uwsgi-plugin-luajit\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI in Stretch and Buster requires very little configuration, since it is already properly packaged. All you need to do is create a symlink to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#notes","title":"Notes","text":"

This file was last updated on June 2019

"},{"location":"INSTALL-ubuntu-18.04-bionic.html","title":"Installation on Ubuntu 18.04 LTS (Bionic)","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in Bionic, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Bionic also ships with Python 3.6, this is an ideal environment for new deployments on both Intel and ARM devices.

"},{"location":"INSTALL-ubuntu-18.04-bionic.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get update\nsudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python-certbot-nginx python-dev python-pip python-virtualenv \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \\\n    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-ubuntu-18.04-bionic.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#notes","title":"Notes","text":"

This file was last updated on November 2018

"},{"location":"INSTALL-ubuntu-22.04-jammy.html","title":"Installation on Ubuntu 22.04 LTS (Jammy)","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in Jammy, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Jammy also ships with Python 3.10, this is an ideal environment for new deployments on both Intel and ARM devices.

"},{"location":"INSTALL-ubuntu-22.04-jammy.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get update\nsudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python3-certbot-nginx \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python3 \\\n    uwsgi-plugin-python3 uwsgi-plugin-tornado-python3\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-ubuntu-22.04-jammy.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#notes","title":"Notes","text":"

This file was last updated on November 2018

"},{"location":"INSTALL.html","title":"Installation","text":"

piku requires Python 3, uWSGI, SSH, and a Linux distribution that runs systemd, such as Raspbian Jessie/Debian 8+/Ubuntu/Fedora/CentOS.

There are 3 ways to install piku on a server:

  1. Manually: Follow INSTALL-x.md for which ever platform. If you are running piku on specific Linux versions, feel free to contribute your own instructions.

  2. Use cloud-init to do it automatically at VPS build time: https://github.com/piku/cloud-init

  3. Use piku-bootstrap to do it once your box is already provisioned: https://github.com/piku/piku-bootstrap

"},{"location":"INSTALL.html#generic-steps-referenced-from-install-x","title":"Generic steps (referenced from INSTALL-x)","text":""},{"location":"INSTALL.html#set-up-the-piku-user","title":"Set up the piku user","text":"

piku requires a separate user account to run. To create a new user with the right group membership (we're using the built-in www-data group because it's generally thought of as a less-privileged group), enter the following command:

# pick a username\nexport PAAS_USERNAME=piku\n# create it\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data $PAAS_USERNAME\n# copy & setup piku.py\nsudo su - $PAAS_USERNAME -c \"wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup\"\n

The setup output should be something like this:

Creating '/home/piku/.piku/apps'.\nCreating '/home/piku/.piku/repos'.\nCreating '/home/piku/.piku/envs'.\nCreating '/home/piku/.piku/uwsgi'.\nCreating '/home/piku/.piku/uwsgi-available'.\nCreating '/home/piku/.piku/uwsgi-enabled'.\nCreating '/home/piku/.piku/logs'.\nSetting '/home/piku/piku.py' as executable.\n
"},{"location":"INSTALL.html#set-up-ssh-access","title":"Set up SSH access","text":"

If you don't have an SSH public key (or never used one before), you need to create one. The following instructions assume you're running some form of UNIX on your own machine (Windows users should check the documentation for their SSH client, unless you have Cygwin installed).

On your own machine, issue the ssh-keygen command and follow the prompts:

ssh-keygen \n\nGenerating public/private rsa key pair.\nEnter file in which to save the key (/home/youruser/.ssh/id_rsa): \nCreated directory '/home/youruser/.ssh'.\nEnter passphrase (empty for no passphrase): \nEnter same passphrase again: \nYour identification has been saved in /home/youruser/.ssh/id_rsa.\nYour public key has been saved in /home/youruser/.ssh/id_rsa.pub.\nThe key fingerprint is:\n85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff youruser@yourlaptop.lan\nThe key's randomart image is:\n+--[ RSA 2048]----+\n<...>\n+-----------------+\n

Copy the resulting id_rsa.pub (or equivalent, just make sure it's the public file) to your piku server and do the following:

sudo su - piku\npython3 piku.py setup:ssh /tmp/id_rsa.pub\n\nAdding key '85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff'.\n

Now if you look at .ssh/authorized_keys, you should see something like this:

sudo su - piku\ncat .ssh/authorized_keys\n\ncommand=\"FINGERPRINT=85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff NAME=default /home/piku/piku.py $SSH_ORIGINAL_COMMAND\",no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhTYZi/qeJBKgU3naI8FNjQgeMYnMsEtqrOmUc4lJoPNH2qBUTNkzwThGqsBm2HNLPURWMiEifBqF+kRixMud67Co7Zs9ys7pwFXkJB9bbZasd2JCGfVZ4UYXHnvgejSWkLAV/4bObhsbP2vWOmbbm91Cwn+PGJgoiW08yrd45lsDmgv9cUAJS3e8LkgVELvIDg49yM5ArB88oxwMEoUgWU2OniHmH0o1zw5I8WXHRhHOjb8cGsdTYfXEizRKKRTM2Mu6dKRt1GNL0UbWi8iS3uJHGD3AcQ4ApdMl5X0gTixKHponStOrSMy19/ltuIy8Sjr7KKPxz07ikMYr7Vpcp youruser@yourlaptop.lan\n

This line is what enables you to SSH (and perform git over SSH operations) to the piku user without a password, verifying your identity via your public key, restricting what can be done remotely and passing on to piku itself the commands you'll be issuing.

"},{"location":"INSTALL.html#test","title":"Test","text":"

From your machine, do:

ssh piku@pi.lan\n\nUsage: piku.py [OPTIONS] COMMAND [ARGS]...\n\n  The smallest PaaS you've ever seen\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  apps              List applications\n  config            Show application configuration\n  config:get        Retrieve a configuration setting\n  config:live       Show live configuration settings\n  config:set        Set a configuration setting\n  deploy            Deploy an application\n  destroy           Destroy an application\n  disable           Disable an application\n  enable            Enable an application\n  logs              Tail an application log\n  ps                Show application worker count\n  ps:scale          Show application configuration\n  restart           Restart an application\n  setup             Initialize paths\n  setup:ssh         Set up a new SSH key\nConnection to pi.lan closed.\n
"},{"location":"PLUGINS.html","title":"PLUGINS","text":"

Thanks to jsenin, piku currently has experimental support for external plugins via #129.

Plugins are inserted into the commands listing and can perform arbitrary actions. At this moment there are no official plugins, but here is an example file that should be placed at ~/.piku/plugins/postgres/__init__.py that could contain the commands to manage a Postgres database:

import click\n\n@click.group()\ndef postgres():\n    \"\"\"Postgres command plugin\"\"\"\n    pass\n\n@postgres.command(\"postgres:create\")\n@click.argument('name')\n@click.argument('user')\n@click.argument('password')\ndef postgres_create():\n    \"\"\"Postgres create a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:drop\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres drops a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:import\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres import a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:dump\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres dumps a database SQL\"\"\"\n    pass\n\ndef cli_commands():\n    return postgres\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html","title":"Setting up a Raspberry Pi Piku Server from Scratch","text":""},{"location":"old/RASPBERRY_PI_QUICKSTART.html#disclaimer","title":"DISCLAIMER!","text":""},{"location":"old/RASPBERRY_PI_QUICKSTART.html#these-instructions-are-correct-as-of-april-1st-2016","title":"These instructions are correct as of April 1st 2016","text":"

Start by flashing a SD card with the latest Raspbian Jessie Lite image.

"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#do-this-in-your-raspberry-pi-as-pi-user","title":"Do this in your Raspberry Pi as 'pi' user","text":"

Boot it, launch raspi-config to perform (at least) the following configuration:

# as 'pi' user\nsudo raspi-config\n

Optionally:

"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#secure-your-install","title":"Secure your install","text":"

Delete the existing SSH keys and recreate them (why? read this).

# as 'pi' user\nsudo rm -v /etc/ssh/ssh_host_*\nsudo dpkg-reconfigure openssh-server\nsudo reboot\n

This will recreate the server keys. Next, update your system:

# as 'pi' user\nsudo apt update\nsudo apt upgrade\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#install-required-packages","title":"Install required packages","text":"

As of April 2016, the shipping versions with Raspbian are recent enough to run piku:

# as 'pi' user\nsudo apt install -y python-virtualenv python-pip git uwsgi uwsgi-plugin-python nginx\nsudo pip install -U click\nsudo reboot\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#meanwhile-go-get-the-goodies-while-raspberry-pi-is-rebooting","title":"Meanwhile, go get the goodies while Raspberry Pi is rebooting","text":"

(We assume you know about ssh keys and have one \"at hand\", you'll need to copy it)

Clone the piku repo somewhere and copy files to your Raspberry Pi

# as yourself in your desktop/laptop computer\nscp piku.py uwsgi-piku.service nginx.default.dist pi@your_machine:/tmp\nscp your_public_ssh_key.pub pi@your_machine:/tmp\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#back-to-the-pi","title":"Back to the Pi","text":"

Prepare uWSGI (part one):

# as 'pi' user\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\nsudo systemctl disable uwsgi\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\nsudo systemctl daemon-reload\nsudo systemctl enable uwsgi-piku\n

Prepare nginx:

sudo apt-get install nginx\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n

Create 'piku' user and set it up

# as 'pi' user\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku\nsudo su - piku\n# this is now done as 'piku' user\nmkdir ~/.ssh\nchmod 700 ~/.ssh\ncp /tmp/piku.py ~/piku.py\npython piku.py setup\npython piku.py setup:ssh /tmp/id_rsa.pub\n# return to 'pi' user\nexit\n

Prepare uWSGI (part two):

# as 'pi' user\nsudo systemctl start uwsgi-piku\nsudo systemctl status uwsgi-piku.service\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#if-youre-still-here-odds-are-your-pi-is-ready-for-work","title":"If you're still here, odds are your Pi is ready for work","text":"

Go back to your machine and try these commands:

# as yourself in your desktop/laptop computer\nssh piku@your_machine\n\nUsage: piku.py [OPTIONS] COMMAND [ARGS]...\n\n  The smallest PaaS you've ever seen\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  apps              List applications\n  config            Show application configuration\n  config:get        Retrieve a configuration setting\n  config:live       Show live configuration settings\n  config:set        Set a configuration setting\n  deploy            Deploy an application\n  destroy           Destroy an application\n  disable           Disable an application\n  enable            Enable an application\n  logs              Tail an application log\n  ps                Show application worker count\n  ps:scale          Show application configuration\n  restart           Restart an application\n  setup             Initialize paths\n  setup:ssh         Set up a new SSH key\nConnection to your_machine closed.\n

If you find any bugs with this quickstart guide, please let Luis Correia know ;)

"},{"location":"old/ROADMAP.html","title":"Roadmap","text":"

This was the original roadmap, filed here in 2019-11-21 for future reference:

"},{"location":"old/SCRIPTS.html","title":"Ubuntu 16.04","text":"

Full installation sequence on a blank Ubuntu 16.04 machine:

sudo apt-get update\nsudo apt-get -y dist-upgrade\nsudo apt-get -y autoremove\nsudo apt-get install -y tmux vim htop fail2ban uwsgi uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python uwsgi-plugin-tornado-python nginx libxml2-dev libxslt1-dev python-dev zlib1g-dev build-essential git python3-virtualenv python3-pip python3-click\nsudo pip3 install -U click pip\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku\n\n# move to /tmp and grab our distribution files\ncd /tmp\nwget https://raw.githubusercontent.com/piku/piku/master/piku.py\nwget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.path\nwget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.service\nwget https://raw.githubusercontent.com/piku/piku/master/nginx.default.dist\nwget https://raw.githubusercontent.com/piku/piku/master/uwsgi-piku.service\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Restart NGINX\nsudo systemctl restart nginx\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n# disable the standard uwsgi startup script\nsudo systemctl disable uwsgi\nsudo systemctl enable uwsgi-piku\nsudo su - piku\nmkdir ~/.ssh\nchmod 700 ~/.ssh\n# now copy the piku script to this user account\ncp /tmp/piku.py ~/piku.py\npython3 piku.py setup\n# Now import your SSH key using setup:ssh\n\nsudo systemctl start uwsgi-piku\n
"}]} \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..1d12769 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"CONTRIBUTING.html","title":"CONTRIBUTING","text":"

We welcome contributions!

"},{"location":"CONTRIBUTING.html#guidelines","title":"Guidelines","text":""},{"location":"DESIGN.html","title":"Design Notes","text":"

The idea behind piku is that it provides the simplest possible way to deploy web apps or services. Simplicity comes at the expense of features, of course, and this document tries to capture the trade-offs.

"},{"location":"DESIGN.html#why-uwsgi","title":"Why uWSGI","text":"

Using uWSGI in emperor mode gives us the following features for free:

"},{"location":"DESIGN.html#application-packaging","title":"Application packaging","text":"

An app is simply a git repository with some additional files on the top level, the most important of which is the Procfile.

"},{"location":"DESIGN.html#procfile-format","title":"Procfile format","text":"

piku recognizes six kinds of process declarations in the Procfile:

So a Python application could have a Procfile like such:

# A module to be loaded by uwsgi to serve HTTP requests\nwsgi: module.submodule:app\n# A background worker\nworker: python long_running_script.py\n# Another worker with a different name\nfetcher: python fetcher.py\n# Simple cron expression: minute [0-59], hour [0-23], day [0-31], month [1-12], weekday [1-7] (starting Monday, no ranges allowed on any field)\ncron: 0 0 * * * python midnight_cleanup.py\nrelease: python initial_cleanup.py\n

...whereas a generic app would be:

web: embedded_server --port $PORT\nworker: background_worker\n

Any worker will be automatically respawned upon failure (uWSGI will automatically shun/throttle crashy workers).

"},{"location":"DESIGN.html#env-settings","title":"ENV settings","text":"

Since piku is targeted at 12 Factor apps, it allows you to set environment variables in a number of ways, the simplest of which is by adding an ENV file to your repository:

SETTING1=foo\n# piku supports comments and variable expansion\nSETTING2=${SETTING1}/bar\n# if this isn't defined, piku will assign a random TCP port\nPORT=9080\n

See ENV.md for a full list of Piku variables which can also be set.

Environment variables can be changed after deployment using config:set.

"},{"location":"DESIGN.html#runtime-detection","title":"Runtime detection","text":"

piku follows a very simple set of rules to determine what kind of runtime is required:

  1. If there's a requirements.txt file at the top level, then the app is assumed to require Python.
  2. TODO: Go
  3. TODO: Node
  4. TODO: Java
  5. For all the rest, a Procfile is required to determine application entry points.
"},{"location":"DESIGN.html#application-isolation","title":"Application isolation","text":"

Application isolation can be tackled at several levels, the most relevant of which being:

For 1.0, all applications run under the same uid, under separate branches of the same filesystem, and without any resource limiting.

Ways to improve upon that (short of full containerisation) typically entail the use of a chroot jail environment (which is available under most POSIX systems in one form or another) or Linux kernel namespaces - both of which are supported by uWSGI (which can also handle resource limiting to a degree).

As to runtime isolation, piku only provides virtualenv support until 1.0. Python apps can run under Python 2 or 3 depending on the setting of PYTHON_VERSION, but will always use pre-installed interpreters (Go, Node and Java support will share these limitations in each major version).

"},{"location":"DESIGN.html#internals","title":"Internals","text":"

piku uses two git repositories for each app: a bare repository for client push, and a clone for deployment (which is efficient in terms of storage since git tries to use hardlinks on local clones whenever possible).

This separation makes it easier to cope with long/large deployments and restore apps to a pristine condition, since the app will only go live after the deployment clone is reset (via git checkout -f).

"},{"location":"DESIGN.html#components","title":"Components","text":"

This diagram (available as a dot file in the img folder) outlines how its components interact:

"},{"location":"ENV.html","title":"Configuring Piku via ENV","text":"

You can configure deployment settings by placing special variables in an ENV file deployed with your app.

"},{"location":"ENV.html#runtime-settings","title":"Runtime Settings","text":""},{"location":"ENV.html#python","title":"Python","text":""},{"location":"ENV.html#node","title":"Node","text":"

NOTE: you will need to stop and re-deploy the app to change the node version in a running app.

"},{"location":"ENV.html#network-settings","title":"Network Settings","text":""},{"location":"ENV.html#uwsgi-settings","title":"uWSGI Settings","text":"

NOTE: UWSGI_IDLE applies to all the workers, so if you have UWSGI_PROCESSES set to 4, they will all be killed simultaneously. Support for progressive scaling of workers via cheaper and similar uWSGI configurations will be added in the future.

"},{"location":"ENV.html#nginx-settings","title":"nginx Settings","text":"

NOTE: if used with Cloudflare, NGINX_HTTPS_ONLY will cause an infinite redirect loop - keep it set to false, use NGINX_CLOUDFLARE_ACL instead and add a Cloudflare Page Rule to \"Always Use HTTPS\" for your server (use domain.name/* to match all URLs).

"},{"location":"ENV.html#nginx-caching","title":"nginx Caching","text":"

When NGINX_CACHE_PREFIXES is set, nginx will cache requests for those URL prefixes to the running application (uwsgi-like or web workers) and reply on its own for NGINX_CACHE_TIME to the outside. This is meant to be used for compute-intensive operations like resizing images or providing large chunks of data that change infrequently (like a sitemap).

The behavior of the cache can be controlled with the following variables:

NOTE: NGINX_CACHE_PATH will be completely managed by nginx and cannot be removed by Piku when the application is destroyed. This is because nginx sets the ownership for the cache to be exclusive to itself, and the piku user cannot remove that file tree. So you will either need to clean it up manually after destroying the app or store it in a temporary filesystem (or set the piku user to the same UID as www-data, which is not recommended).

Right now, there is no provision for cache revalidation (i.e., nginx asking your backend if the cache entries are still valid), since that requires active application logic that varies depending on the runtime--nginx will only ask your backend for new content when NGINX_CACHE_TIME elapses. If you require that kind of behavior, that is still possible via NGINX_INCLUDE_FILE.

Also, keep in mind that using nginx caching with a static website worker will not work (and there's no point to it either).

"},{"location":"ENV.html#nginx-overrides","title":"nginx Overrides","text":""},{"location":"ENV.html#acme-settings","title":"Acme Settings","text":""},{"location":"FAQ.html","title":"FAQ","text":"

Q: Why piku?

A: Partly because it's supposed to run on a Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because I know the name will annoy some of my friends.

Q: Why Python/why not Go?

A: I actually thought about doing this in Go right off the bat, but click is so cool and I needed to have uWSGI running anyway, so I caved in. But I'm very likely to take something like suture and port this across, doing away with uWSGI altogether.

Go also (at the time) did not have a way to vendor dependencies that I was comfortable with, and that is also why Go support fell behind. Hopefully that will change soon.

Q: Does it run under Python 3?

A: Right now, it only runs on Python 3, even though it can deploy apps written in both major versions. It began its development using 2.7 and usingclick for abstracting the simpler stuff, and I eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since I wanted to make installing it on the Raspberry Pi as simple as possible.

Q: Why not just use dokku?

A: I used dokku daily for most of my personal stuff for a good while. But it relied on a number of x64 containers that needed to be completely rebuilt for ARM, and when I decided I needed something like this (March 2016) that was barely possible - docker itself was not fully baked for ARM yet, and people were at the time trying to get herokuish and buildstep to build on ARM.

"},{"location":"INSTALL-centos-9.html","title":"Installation on CentOS 9","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

All steps done as root (or add sudo if you prefer).

"},{"location":"INSTALL-centos-9.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

dnf in -y ansible-core ansible-collection-ansible-posix ansible-collection-ansible-utils nginx nodejs npm openssl postgresql postgresql-server postgresql-contrib python3 python3-pip uwsgi uwsgi-logger-file uwsgi-logger-systemd\npip install click\n
"},{"location":"INSTALL-centos-9.html#set-up-the-piku-user","title":"Set up the piku user","text":"
adduser --groups nginx piku\n# copy & setup piku.py\nsu - piku -c \"wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup\"\n
"},{"location":"INSTALL-centos-9.html#set-up-ssh-access","title":"Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-centos-9.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

FYI The uWSGI Emperor \u2013 multi-app deployment

mv /home/piku/.piku/uwsgi/uwsgi.ini /etc/uwsgi.d/piku.ini # linking alone increases the host attack service if one can get inside the piku user or one of its apps, so moving is safer\nchown piku:piku /etc/uwsgi.d/piku.ini # In Tyrant mode (set by default in /etc/uwsgi.ini) the Emperor will run the vassal using the UID/GID of the vassal configuration file\nsystemctl restart uwsgi\njournalctl -feu uwsgi # see logs\n
"},{"location":"INSTALL-centos-9.html#nginx-configuration","title":"nginx Configuration","text":"

FYI Setting up and configuring NGINX

echo \"include /home/piku/.piku/nginx/*.conf;\" > /etc/nginx/conf.d/piku.conf\nsystemctl restart nginx\njournalctl -feu nginx # see logs\n
"},{"location":"INSTALL-centos-9.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsu -\ngit clone https://github.com/piku/piku.git # need a copy of some files\ncp -v piku/piku-nginx.{path,service} /etc/systemd/system/\nsystemctl enable piku-nginx.{path,service}\nsystemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `active: active (waiting)`\n
"},{"location":"INSTALL-centos-9.html#notes","title":"Notes","text":""},{"location":"INSTALL-other.html","title":"Installation on other platforms","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

"},{"location":"INSTALL-other.html#dependencies","title":"Dependencies","text":"

Before running piku for the first time, you need to install the following Python packages at the system level:

"},{"location":"INSTALL-other.html#raspbian-jessie-debian-8-ubuntu-1604","title":"Raspbian Jessie, Debian 8, Ubuntu 16.04","text":"
sudo apt-get install git python3-virtualenv python3-pip\nsudo pip3 install -U click\n
"},{"location":"INSTALL-other.html#raspbian-wheezy","title":"Raspbian Wheezy","text":"
sudo apt-get install git python3\nsudo easy_install3 -U pip3\nsudo pip3 install -U click virtualenv\n

These may or may not be installed already (click usually isn't). For Raspbian Wheezy this is the preferred approach, since current apt packages are fairly outdated.

"},{"location":"INSTALL-other.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-other.html#uwsgi-installation-debian-linux-variants-any-architecture","title":"uWSGI Installation (Debian Linux variants, any architecture)","text":"

uWSGI can be installed in a variety of fashions. These instructions cover both pre-packaged and source installs depending on your system.

"},{"location":"INSTALL-other.html#raspbian-jessie-debian-8","title":"Raspbian Jessie, Debian 8","text":"

Warning

These OS releases are no longer supported and these instructions are kept for reference purposes only.

In Raspbian Jessie, Debian 8 and other systemd distributions where uWSGI is already available pre-compiled (but split into a number of plugins), do the following:

# At the time of this writing, this installs uwsgi 2.0.7 on Raspbian Jessie.\n# You can also install uwsgi-plugins-all if you want to get runtime support for other languages\nsudo apt-get install uwsgi uwsgi-plugin-python3\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n# disable the standard uwsgi startup script\nsudo systemctl disable uwsgi\n\n# add our own startup script\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\nsudo systemctl enable uwsgi-piku\nsudo systemctl start uwsgi-piku\n\n# check it's running\nsudo systemctl status uwsgi-piku.service\n
Important Note: Make sure you run piku.py setup as outlined above before starting the service.

Also, please note that uwsgi-piku.service, as provided, creates a /run/uwsgi-piku directory for it to place socket files and sundry. This is not actually used at the moment, since the uwsgi socket file is placed inside the piku user directory for consistency across OS distributions. This will be cleaned up in a later release.

"},{"location":"INSTALL-other.html#raspbian-wheezy_1","title":"Raspbian Wheezy","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

Since Raspbian Wheezy is a fairly old distribution by now, its uwsgi-* packages are completely outdated (and depend on Python 2.6), so we have to compile and install our own version, as well as using an old-style init script to have it start automatically upon boot.

sudo apt-get install build-essential python-dev libpcre3-dev\n# At the time of this writing, this installs 2.0.12\nsudo pip install uwsgi\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n\n# set up our init script\nsudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku\nsudo chmod +x /etc/init.d/uwsgi-piku\nsudo update-rc.d uwsgi-piku defaults\nsudo service uwsgi-piku start\n
Important Note: Make sure you run python3 piku.py setup as outlined above before starting the service.

"},{"location":"INSTALL-other.html#ubuntu-1404-lts","title":"Ubuntu 14.04 LTS","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

This is a mix of both the above, and should change soon when we get 16.04. If you have trouble, install uWSGI via pip instead.

# At the time of this writing, this installs uwsgi 1.9.17 on Ubuntu 14.04 LTS.\n# You can also install uwsgi-plugins-all if you want to get runtime support for other languages\nsudo apt-get install uwsgi uwsgi-plugin-python3\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n\n# set up our init script\nsudo cp /tmp/uwsgi-piku.dist /etc/init.d/uwsgi-piku\nsudo chmod +x /etc/init.d/uwsgi-piku\nsudo update-rc.d uwsgi-piku defaults\nsudo service uwsgi-piku start\n
"},{"location":"INSTALL-other.html#nginx-installation-raspbian-8-ubuntu-1604","title":"nginx Installation (Raspbian 8, Ubuntu 16.04)","text":"

Warning

These OS releases are no longer supported and these instructions are kept for reference purposes only.

PLEASE NOTE: There is a bug in nginx 1.6.2 under Raspbian 8 that causes it to try to allocate around a gigabyte of RAM when using SSL with SPDY. I seriously recommend using Ubuntu instead, if you can, or disabling SSL altogether.

sudo apt-get install nginx\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-other.html#java-8-installation-all-debian-linux-variants-on-raspberry-pi","title":"Java 8 Installation (All Debian Linux variants, on Raspberry Pi)","text":"

Warning

OpenJDK 8 is no longer shipping with most distributions and these instructions are kept for reference purposes only.

To be able to deploy Java apps, we're going to need to install Java (and, since we're going to be doing so on ARM, it's best to use Oracle's runtime). To do that, we're going to use the webupd8team PPA, which has a (cross-platform) Java installer.

First, get rid of OpenJDK and import the PPA key:

sudo apt-get remove openjdk*\nsudo apt-key adv --recv-key --keyserver keyserver.ubuntu.com EEA14886\n
"},{"location":"INSTALL-other.html#raspbian-jessie","title":"Raspbian Jessie","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

For Jessie, we're going to use the trusty version of the installer:

sudo tee /etc/apt/sources.list.d/webupd8team.list\ndeb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main \ndeb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main\n^D\n
"},{"location":"INSTALL-other.html#ubuntu-1604-for-arm","title":"Ubuntu 16.04 for ARM","text":"

Warning

This OS release is no longer supported and these instructions are kept for reference purposes only.

For Xenial, we're going to use its own version:

sudo tee /etc/apt/sources.list.d/webupd8team.list\ndeb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main \ndeb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main\n^D\n

Now perform the actual install:

sudo apt-get update\nsudo apt-get install oracle-java8-installer oracle-java8-set-default\n
"},{"location":"INSTALL-other.html#go-installation-all-debian-linux-variants-on-raspberry-pi","title":"Go Installation (All Debian Linux variants, on Raspberry Pi)","text":"

This is EXPERIMENTAL and may not work at all.

"},{"location":"INSTALL-other.html#raspbian-wheezyjessie","title":"Raspbian Wheezy/Jessie","text":"

Warning

Wheezy and Jessie are no longer supported and these instructions are kept for reference purposes only.

Since Raspbian's Go compiler is version 1.0.2, we need something more up-to-date.

  1. Get an ARM 6 binary tarball
  2. Unpack it under the piku user like such:
sudo su - piku\ntar -zxvf /tmp/go1.5.3.linux-arm.tar.gz\n# remove unnecessary files\nrm -rf go/api go/blog go/doc go/misc go/test\n
  1. Give it a temporary GOPATH and install godep:
sudo su - piku\nGOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get github.com/tools/godep\n# temporary workaround until this is fixed in godep or Go 1.7(?)\nGOROOT=$HOME/go GOPATH=$HOME/gopath PATH=$PATH:$HOME/go/bin go get golang.org/x/sys/unix\n

TODO: complete this.

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html","title":"Installation on Raspbian Stretch or Buster","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in modern Debian versions, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. However, Stretch still ships with Python 3.5, which means it's not an ideal environment for new deployments on both Intel and ARM devices (Buster, in turn, ships with Python 3.7).

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#setting-up-your-raspberry-pi","title":"Setting up your Raspberry Pi","text":"

Download and install Raspbian onto an SD card.

After you install it is recommended that you do the following to update your installation to the latest available software.

# update apt-get\nsudo apt-get update\n\n# upgrade all software\nsudo apt-get upgrade\n

Configure your installation. It is recommended that Change Password from the default and setup Locale Options (Locale and Timezone) and EXPAND FILESYSTEM. You will also want to Enable SSH.

# configure your installation\nsudo raspi-config\n

At this point it is a good idea to sudo shutdown -h now and make a backup image of the card.

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python-certbot-nginx python-dev python-pip python-virtualenv \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \\\n    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python \\\n    uwsgi-plugin-lua5.1 uwsgi-plugin-lua5.2 uwsgi-plugin-luajit\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI in Stretch and Buster requires very little configuration, since it is already properly packaged. All you need to do is create a symlink to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-raspbian-9.4-stretch-10-buster.html#notes","title":"Notes","text":"

This file was last updated on June 2019

"},{"location":"INSTALL-ubuntu-18.04-bionic.html","title":"Installation on Ubuntu 18.04 LTS (Bionic)","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in Bionic, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Bionic also ships with Python 3.6, this is an ideal environment for new deployments on both Intel and ARM devices.

"},{"location":"INSTALL-ubuntu-18.04-bionic.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get update\nsudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python-certbot-nginx python-dev python-pip python-virtualenv \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python \\\n    uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-tornado-python\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-ubuntu-18.04-bionic.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-ubuntu-18.04-bionic.html#notes","title":"Notes","text":"

This file was last updated on November 2018

"},{"location":"INSTALL-ubuntu-22.04-jammy.html","title":"Installation on Ubuntu 22.04 LTS (Jammy)","text":"

This is a standalone, distribution-specific version of INSTALL.md. You do not need to read or follow the original file, but can refer to it for generic steps like setting up SSH keys (which are assumed to be common knowledge here)

piku setup is simplified in Jammy, since it can take advantage of some packaging improvements in uWSGI and does not require a custom systemd service. Since Jammy also ships with Python 3.10, this is an ideal environment for new deployments on both Intel and ARM devices.

"},{"location":"INSTALL-ubuntu-22.04-jammy.html#dependencies","title":"Dependencies","text":"

Before installing piku, you need to install the following packages:

sudo apt-get update\nsudo apt-get install -y build-essential certbot git \\\n    libjpeg-dev libxml2-dev libxslt1-dev zlib1g-dev nginx \\\n    python3-certbot-nginx \\\n    python3-dev python3-pip python3-click python3-virtualenv \\\n    uwsgi uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python3 \\\n    uwsgi-plugin-python3 uwsgi-plugin-tornado-python3\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#set-up-the-piku-user-set-up-ssh-access","title":"Set up the piku user, Set up SSH access","text":"

See INSTALL.md

"},{"location":"INSTALL-ubuntu-22.04-jammy.html#uwsgi-configuration","title":"uWSGI Configuration","text":"

uWSGI requires very little configuration, since it is already properly packaged. All you need to do is place a link to the piku configuration file in /etc/uwsgi/apps-enabled:

sudo ln /home/$PAAS_USERNAME/.piku/uwsgi/uwsgi.ini /etc/uwsgi/apps-enabled/piku.ini\nsudo systemctl restart uwsgi\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#nginx-configuration","title":"nginx Configuration","text":"

piku requires you to edit /etc/nginx/sites-available/default to the following, so it can inject new site configurations into nginx:

server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    root /var/www/html;\n    index index.html index.htm;\n    server_name _;\n    location / {\n        try_files $uri $uri/ =404;\n    }\n}\n# replace `PAAS_USERNAME` with the username you created.\ninclude /home/PAAS_USERNAME/.piku/nginx/*.conf;\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#set-up-systemdpath-to-reload-nginx-upon-config-changes","title":"Set up systemd.path to reload nginx upon config changes","text":"
# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n
"},{"location":"INSTALL-ubuntu-22.04-jammy.html#notes","title":"Notes","text":"

This file was last updated on November 2018

"},{"location":"INSTALL.html","title":"Installation","text":"

piku requires Python 3, uWSGI, SSH, and a Linux distribution that runs systemd, such as Raspbian Jessie/Debian 8+/Ubuntu/Fedora/CentOS.

There are 3 ways to install piku on a server:

  1. Manually: Follow INSTALL-x.md for which ever platform. If you are running piku on specific Linux versions, feel free to contribute your own instructions.

  2. Use cloud-init to do it automatically at VPS build time: https://github.com/piku/cloud-init

  3. Use piku-bootstrap to do it once your box is already provisioned: https://github.com/piku/piku-bootstrap

"},{"location":"INSTALL.html#generic-steps-referenced-from-install-x","title":"Generic steps (referenced from INSTALL-x)","text":""},{"location":"INSTALL.html#set-up-the-piku-user","title":"Set up the piku user","text":"

piku requires a separate user account to run. To create a new user with the right group membership (we're using the built-in www-data group because it's generally thought of as a less-privileged group), enter the following command:

# pick a username\nexport PAAS_USERNAME=piku\n# create it\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data $PAAS_USERNAME\n# copy & setup piku.py\nsudo su - $PAAS_USERNAME -c \"wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup\"\n

The setup output should be something like this:

Creating '/home/piku/.piku/apps'.\nCreating '/home/piku/.piku/repos'.\nCreating '/home/piku/.piku/envs'.\nCreating '/home/piku/.piku/uwsgi'.\nCreating '/home/piku/.piku/uwsgi-available'.\nCreating '/home/piku/.piku/uwsgi-enabled'.\nCreating '/home/piku/.piku/logs'.\nSetting '/home/piku/piku.py' as executable.\n
"},{"location":"INSTALL.html#set-up-ssh-access","title":"Set up SSH access","text":"

If you don't have an SSH public key (or never used one before), you need to create one. The following instructions assume you're running some form of UNIX on your own machine (Windows users should check the documentation for their SSH client, unless you have Cygwin installed).

On your own machine, issue the ssh-keygen command and follow the prompts:

ssh-keygen \n\nGenerating public/private rsa key pair.\nEnter file in which to save the key (/home/youruser/.ssh/id_rsa): \nCreated directory '/home/youruser/.ssh'.\nEnter passphrase (empty for no passphrase): \nEnter same passphrase again: \nYour identification has been saved in /home/youruser/.ssh/id_rsa.\nYour public key has been saved in /home/youruser/.ssh/id_rsa.pub.\nThe key fingerprint is:\n85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff youruser@yourlaptop.lan\nThe key's randomart image is:\n+--[ RSA 2048]----+\n<...>\n+-----------------+\n

Copy the resulting id_rsa.pub (or equivalent, just make sure it's the public file) to your piku server and do the following:

sudo su - piku\npython3 piku.py setup:ssh /tmp/id_rsa.pub\n\nAdding key '85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff'.\n

Now if you look at .ssh/authorized_keys, you should see something like this:

sudo su - piku\ncat .ssh/authorized_keys\n\ncommand=\"FINGERPRINT=85:29:07:cb:de:ad:be:ef:42:65:00:c8:d2:6b:9e:ff NAME=default /home/piku/piku.py $SSH_ORIGINAL_COMMAND\",no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhTYZi/qeJBKgU3naI8FNjQgeMYnMsEtqrOmUc4lJoPNH2qBUTNkzwThGqsBm2HNLPURWMiEifBqF+kRixMud67Co7Zs9ys7pwFXkJB9bbZasd2JCGfVZ4UYXHnvgejSWkLAV/4bObhsbP2vWOmbbm91Cwn+PGJgoiW08yrd45lsDmgv9cUAJS3e8LkgVELvIDg49yM5ArB88oxwMEoUgWU2OniHmH0o1zw5I8WXHRhHOjb8cGsdTYfXEizRKKRTM2Mu6dKRt1GNL0UbWi8iS3uJHGD3AcQ4ApdMl5X0gTixKHponStOrSMy19/ltuIy8Sjr7KKPxz07ikMYr7Vpcp youruser@yourlaptop.lan\n

This line is what enables you to SSH (and perform git over SSH operations) to the piku user without a password, verifying your identity via your public key, restricting what can be done remotely and passing on to piku itself the commands you'll be issuing.

"},{"location":"INSTALL.html#test","title":"Test","text":"

From your machine, do:

ssh piku@pi.lan\n\nUsage: piku.py [OPTIONS] COMMAND [ARGS]...\n\n  The smallest PaaS you've ever seen\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  apps              List applications\n  config            Show application configuration\n  config:get        Retrieve a configuration setting\n  config:live       Show live configuration settings\n  config:set        Set a configuration setting\n  deploy            Deploy an application\n  destroy           Destroy an application\n  disable           Disable an application\n  enable            Enable an application\n  logs              Tail an application log\n  ps                Show application worker count\n  ps:scale          Show application configuration\n  restart           Restart an application\n  setup             Initialize paths\n  setup:ssh         Set up a new SSH key\nConnection to pi.lan closed.\n
"},{"location":"PLUGINS.html","title":"PLUGINS","text":"

Thanks to jsenin, piku currently has experimental support for external plugins via #129.

Plugins are inserted into the commands listing and can perform arbitrary actions. At this moment there are no official plugins, but here is an example file that should be placed at ~/.piku/plugins/postgres/__init__.py that could contain the commands to manage a Postgres database:

import click\n\n@click.group()\ndef postgres():\n    \"\"\"Postgres command plugin\"\"\"\n    pass\n\n@postgres.command(\"postgres:create\")\n@click.argument('name')\n@click.argument('user')\n@click.argument('password')\ndef postgres_create():\n    \"\"\"Postgres create a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:drop\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres drops a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:import\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres import a database\"\"\"\n    pass\n\n@postgres.command(\"postgres:dump\")\n@click.argument('name')\ndef postgres_drop():\n    \"\"\"Postgres dumps a database SQL\"\"\"\n    pass\n\ndef cli_commands():\n    return postgres\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html","title":"Setting up a Raspberry Pi Piku Server from Scratch","text":""},{"location":"old/RASPBERRY_PI_QUICKSTART.html#disclaimer","title":"DISCLAIMER!","text":""},{"location":"old/RASPBERRY_PI_QUICKSTART.html#these-instructions-are-correct-as-of-april-1st-2016","title":"These instructions are correct as of April 1st 2016","text":"

Start by flashing a SD card with the latest Raspbian Jessie Lite image.

"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#do-this-in-your-raspberry-pi-as-pi-user","title":"Do this in your Raspberry Pi as 'pi' user","text":"

Boot it, launch raspi-config to perform (at least) the following configuration:

# as 'pi' user\nsudo raspi-config\n

Optionally:

"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#secure-your-install","title":"Secure your install","text":"

Delete the existing SSH keys and recreate them (why? read this).

# as 'pi' user\nsudo rm -v /etc/ssh/ssh_host_*\nsudo dpkg-reconfigure openssh-server\nsudo reboot\n

This will recreate the server keys. Next, update your system:

# as 'pi' user\nsudo apt update\nsudo apt upgrade\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#install-required-packages","title":"Install required packages","text":"

As of April 2016, the shipping versions with Raspbian are recent enough to run piku:

# as 'pi' user\nsudo apt install -y python-virtualenv python-pip git uwsgi uwsgi-plugin-python nginx\nsudo pip install -U click\nsudo reboot\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#meanwhile-go-get-the-goodies-while-raspberry-pi-is-rebooting","title":"Meanwhile, go get the goodies while Raspberry Pi is rebooting","text":"

(We assume you know about ssh keys and have one \"at hand\", you'll need to copy it)

Clone the piku repo somewhere and copy files to your Raspberry Pi

# as yourself in your desktop/laptop computer\nscp piku.py uwsgi-piku.service nginx.default.dist pi@your_machine:/tmp\nscp your_public_ssh_key.pub pi@your_machine:/tmp\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#back-to-the-pi","title":"Back to the Pi","text":"

Prepare uWSGI (part one):

# as 'pi' user\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\nsudo systemctl disable uwsgi\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\nsudo systemctl daemon-reload\nsudo systemctl enable uwsgi-piku\n

Prepare nginx:

sudo apt-get install nginx\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Check the status of piku-nginx.service\nsystemctl status piku-nginx.path # should return `Active: active (waiting)`\n# Restart NGINX\nsudo systemctl restart nginx\n

Create 'piku' user and set it up

# as 'pi' user\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku\nsudo su - piku\n# this is now done as 'piku' user\nmkdir ~/.ssh\nchmod 700 ~/.ssh\ncp /tmp/piku.py ~/piku.py\npython piku.py setup\npython piku.py setup:ssh /tmp/id_rsa.pub\n# return to 'pi' user\nexit\n

Prepare uWSGI (part two):

# as 'pi' user\nsudo systemctl start uwsgi-piku\nsudo systemctl status uwsgi-piku.service\n
"},{"location":"old/RASPBERRY_PI_QUICKSTART.html#if-youre-still-here-odds-are-your-pi-is-ready-for-work","title":"If you're still here, odds are your Pi is ready for work","text":"

Go back to your machine and try these commands:

# as yourself in your desktop/laptop computer\nssh piku@your_machine\n\nUsage: piku.py [OPTIONS] COMMAND [ARGS]...\n\n  The smallest PaaS you've ever seen\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  apps              List applications\n  config            Show application configuration\n  config:get        Retrieve a configuration setting\n  config:live       Show live configuration settings\n  config:set        Set a configuration setting\n  deploy            Deploy an application\n  destroy           Destroy an application\n  disable           Disable an application\n  enable            Enable an application\n  logs              Tail an application log\n  ps                Show application worker count\n  ps:scale          Show application configuration\n  restart           Restart an application\n  setup             Initialize paths\n  setup:ssh         Set up a new SSH key\nConnection to your_machine closed.\n

If you find any bugs with this quickstart guide, please let Luis Correia know ;)

"},{"location":"old/ROADMAP.html","title":"Roadmap","text":"

This was the original roadmap, filed here in 2019-11-21 for future reference:

"},{"location":"old/SCRIPTS.html","title":"Ubuntu 16.04","text":"

Full installation sequence on a blank Ubuntu 16.04 machine:

sudo apt-get update\nsudo apt-get -y dist-upgrade\nsudo apt-get -y autoremove\nsudo apt-get install -y tmux vim htop fail2ban uwsgi uwsgi-plugin-python uwsgi-plugin-python3 uwsgi-plugin-asyncio-python3 uwsgi-plugin-gevent-python uwsgi-plugin-tornado-python nginx libxml2-dev libxslt1-dev python-dev zlib1g-dev build-essential git python3-virtualenv python3-pip python3-click\nsudo pip3 install -U click pip\nsudo adduser --disabled-password --gecos 'PaaS access' --ingroup www-data piku\n\n# move to /tmp and grab our distribution files\ncd /tmp\nwget https://raw.githubusercontent.com/piku/piku/master/piku.py\nwget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.path\nwget https://raw.githubusercontent.com/piku/piku/master/piku-nginx.service\nwget https://raw.githubusercontent.com/piku/piku/master/nginx.default.dist\nwget https://raw.githubusercontent.com/piku/piku/master/uwsgi-piku.service\n# Set up nginx to pick up our config files\nsudo cp /tmp/nginx.default.dist /etc/nginx/sites-available/default\n# Set up systemd.path to reload nginx upon config changes\nsudo cp ./piku-nginx.{path, service} /etc/systemd/system/\nsudo systemctl enable piku-nginx.{path,service}\nsudo systemctl start piku-nginx.path\n# Restart NGINX\nsudo systemctl restart nginx\nsudo cp /tmp/uwsgi-piku.service /etc/systemd/system/\n# refer to our executable using a link, in case there are more versions installed\nsudo ln -s `which uwsgi` /usr/local/bin/uwsgi-piku\n# disable the standard uwsgi startup script\nsudo systemctl disable uwsgi\nsudo systemctl enable uwsgi-piku\nsudo su - piku\nmkdir ~/.ssh\nchmod 700 ~/.ssh\n# now copy the piku script to this user account\ncp /tmp/piku.py ~/piku.py\npython3 piku.py setup\n# Now import your SSH key using setup:ssh\n\nsudo systemctl start uwsgi-piku\n
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..0f8724e --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..19f5705 Binary files /dev/null and b/sitemap.xml.gz differ