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..68dd225 --- /dev/null +++ b/404.html @@ -0,0 +1,906 @@ + + + +
+ + + + + + + + + + + + + + +Q: Why piku
?
A: Partly because it's started out on the Raspberry Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because we knew the name would be cute and amusing.
+Q: Why Python/why not Go?
+A: We actually thought about doing this in Go right off the bat, but click is so cool and we needed to have uwsgi
running anyway, so we caved in. But possible future directions are likely to take something like suture and port this across (or just use Caddy), doing away with uwsgi
altogether.
Go also (at the time) did not have a way to vendor dependencies that we were 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 we eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since we wanted to make installing it on the Raspberry Pi as simple as possible.
Q: Why not just use dokku
?
A: We used dokku
daily for many projects. But it relied on a number of x64
containers that needed to be completely rebuilt for ARM
, and when we decided we 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 just starting to get herokuish
and buildstep
to build on ARM
.
piku
is a stable project, but we welcome contributions that:
piku
in various Linux distributions and environments (check the sister repositories in the project)By its very nature, piku
is a very small program. By today's standards of all-encompassing solutions this may seem strange, but it would benefit from being kept that way.
from os.path import abspath
PEP8
.So please keep that in mind when contributing.
+For instance, if your runtime or framework needs additional setup, it might be better to contribute an utility script to run in a release
entry in the Procfile
rather than patching piku.py
--but do hack at it if that is the best way to achieve it.
Besides the bundled examples, there are a number of community-contributed examples that can be deployed using piku
.
They are meant to be illustrative of the kinds of applications that can be deployed using piku
, and are not meant to be exhaustive.
piku
apps, written in ClojureScriptThere is an active discussion forum for piku
where you can ask questions, share your deployments, and discuss new features, and we have a published roadmap.
+ + Contributing + + + Examples + +
+ + + + + + + + + + + + + +ENV
VariablesYou can configure deployment settings by placing special variables in an ENV
file deployed with your app. This file should be placed in the root of your app's directory, and can look something like this:
# variables are global and can be replaced
+SETTING1=True
+SETTING2=${SETTING1}/Maybe
+
+# addr:port
+PORT=9080
+BIND_ADDRESS=0.0.0.0
+
+# the max number the worker will process
+RANGE=10
+
+# worker sleep interval between prints
+INTERVAL=1
+
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_VERSION
(int): Forces Python 3Warning
+This is mostly deprecated (since piku
now runs solely on Python 3.x), but is kept around for legacy compatibility.
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.
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 connectionsUWSGI_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
pluginUWSGI_ASYNCIO
(integer): enable the Python 2/3 asyncio
plugin and set the number of tasksUWSGI_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
SettingsNGINX_SERVER_NAME
: set the virtual host name associated with your appNGINX_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 IPsNGINX_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
CachingWhen 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 GBNGINX_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
OverridesNGINX_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_ROOT_CA
: set the certificate authority that Acme should use to generate public ssl certificates (string, default: letsencrypt.org
)A minimal piku
app has a root directory structure similar to this:
ENV
+Procfile
+app.py
+worker.py
+requirements.txt
+
+ + ENV + + + Procfile + +
+piku
relies on two configuration files shipped with your app to determine how to run it: ENV
and Procfile
.
ENV
file contains environment variables that allow you to configure both piku
and your app, following the 12-factor app approach.Procfile
tells piku
what kind of workers to runBesides ENV
and Procfile
, piku
also looks for runtime-specific files in the root of your app's directory:
requirements.txt
file at the top level, then the app is assumed to require Python.Gemfile
at the top level, then the app is assumed to require Ruby.package.json
file at the top level, then the app is assumed to require Node.js.pom.xml
or a build.gradle
file at the top level, then the app is assumed to require Java.deps.edn
or project.clj
file at the top level, then the app is assumed to require Clojure.Godeps
file at the top level, then the app is assumed to require Go.Info
+go.mod
support is currently in development.
These are not exclusive, however. There is also a sample Phoenix app that demonstrates how to add support for additional runtimes.
+ + + + + + + + + + + + + +Procfile
formatpiku
supports a Heroku-like Procfile
that you provide to indicate how to run one or more application processes (what Heroku calls "dynos"):
web: embedded_server --port $PORT
+worker: background_worker
+
piku
supports six different kinds of worker processes:
# A module to be loaded by uwsgi to serve HTTP requests
+wsgi: module.submodule:app
+# A background worker, using the default name
+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
+
wsgi
wsgi
workers are Python-specific and must be specified in the format dotted.module:entry_point
. uwsgi
will load the specified module and call the entry_point
function to start the application, handling all the HTTP requests directly (your Python code will run the handlers, but will run as a part of the uwsgi
process).
uwsgi
will automatically spawn multiple workers for you, and you can control the number of workers via the UWSGI_PROCESSES
environment variable.
Also, in this mode uwsgi
will talk to nginx
via a Unix socket, so you don't need to worry about the HTTP server at all.
web
web
workers can be literally any executable that uwsgi
can run and that will serve HTTP requests. They must (by convention) honor the PORT
environment variable, so that the nginx
reverse proxy can talk to them.
worker
worker
processes are just standard processes that run in the background. They can actually have arbitrary names, and the idea is that they would perform any tasks your app requires that isn't directly related to serving web pages.
static
static
workers are simply a way to direct nginx
to mount the first argument as a static path and serve it directly. This is useful for serving (and caching) static files directly from your app, without having to go through application code.
Note
+See nginx
caching for more information on how to configure nginx
to serve static files.
cron
A cron
worker is a process that runs at a specific time (or intervals), using a simplified crontab
expression preceding the command to be run (e.g. cron: */5 * * * * python batch.py
to run a batch every 5 minutes)
Warning
+crontab
expressions are simplified and do not support ranges or lists, only single values, splits and *
(wildcard).
preflight
preflight
is a special "worker" that is run once before the app is deployed and dependencies are installed (can be useful for cleanups, like resetting caches, removing older versions of files, etc).
release
release
which is a special worker that is run once when the app is deployed, after installing dependencies (can be useful for build steps).
Any worker will be automatically respawned upon failure ([uWSGI][uwsgi] will automatically shun/throttle crashy workers).
+ + + + + + + + + + + + + +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.
git
, ssh
, uwsgi
, nginx
).Using uWSGI in emperor mode gives us the following features for free:
+virtualenv
integrationuid
/gid
on a per-app basis (if necessary)An app is simply a git
repository with some additional files on the top level, the most important of which is the Procfile
.
ENV
settingsSince 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 configuration for a full list of environment variables that can also be set.
+Environment variables can be changed after deployment using the config:set
command.
piku
follows a very simple set of rules to determine what kind of runtime is required, outlined in the configuration section
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).
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
).
This diagram outlines how its components interact:
+graph TD
+ subgraph "systemd"
+ nginx([nginx])
+ sshd([sshd])
+ uwsgi([uwsgi])
+ end
+ uwsgi-->vassal([vassal])
+ vassal-.->uwsgi.ini
+ sshd-->piku([piku.py])-->repo[git repo]
+ Procfile-->uwsgi.ini
+ an-->app
+ repo---app
+ repo---ENV
+ repo---requirements.txt
+ repo---Procfile
+ requirements.txt-->virtualenv
+ uwsgi.ini-->virtualenv
+ ENV-->an
+ ENV-->uwsgi.ini
+ nginx-.-mn[master<br>nginx.conf]
+ mn-.-an[app<br>nginx.conf]
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name:
+ git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).virtualenv
.GOPATH
for each app.package.json
into node_modules
.pom.xml
or build.gradle
file.leiningen
or the Clojure CLI and a deps.edn
file.bundle install
of your gems in an isolated folder.Procfile
and starts the relevant workers using uwsgi
as a generic process manager.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file.You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
has full virtual host support - i.e., you can host multiple apps on the same VPS and use DNS aliases to access them via different hostnames.
piku
will also set up either a private certificate or obtain one via Let's Encrypt to enable SSL.
If you are on a LAN and are accessing piku
from macOS/iOS/Linux clients, you can try using piku/avahi-aliases
to announce different hosts for the same IP address via Avahi/mDNS/Bonjour.
Besides static sites, piku
also supports directly mapping specific URL prefixes to filesystem paths (to serve static assets) or caching back-end responses (to remove load from applications).
These features are configured by setting appropriate values in the ENV
file.
piku
is intended to work in any POSIX-like environment where you have Python, nginx
, uwsgi
and ssh
: it has been deployed on Linux, FreeBSD, [Cygwin][cygwin] and the [Windows Subsystem for Linux][wsl].
As a baseline, it began its development on an original 256MB Rasbperry Pi Model B, and still runs reliably on it.
+But its main use is as a micro-PaaS to run applications on cloud servers with both Intel and ARM CPUs, with either Debian or Ubuntu Linux as target platforms.
+piku
currently supports apps written in Python, Node, Clojure, Java and a few other languages (like Go) in the works.
But as a general rule, if it can be invoked from a shell, it can be run inside piku
.
piku
, inspired by dokku
, allows you do git push
deployments to your own servers, no matter how small they are.
+
+
piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name:
+ git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).Procfile
and starts matching worker processes.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file. You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
is considered STABLE. It is actively maintained, but "actively" here means the feature set is pretty much done, so it is only updated when new language runtimes are added or reproducible bugs crop up.
It currently requires Python 3.7 or above, since even though 3.8+ is now the baseline Python 3 version in Ubuntu LTS 20.04 and Debian 11 has already moved on to 3.9, there are no substantial differences between those versions.
+Since most of its users run it on LTS distributions, there is no rush to introduce disruption. The current plan is to throw up a warning for older runtimes and do regression testing for 3.7-3.12 (replacing the current bracket of tests from 3.5 to 3.8), and make sure we also cover Ubuntu 22.04, Debian 11 and Fedora 37+.
+ + + + + + + + + + + + + +Note
+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).
+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
+
piku
useradduser --groups nginx piku
+# copy & setup piku.py
+su - piku -c "wget https://raw.githubusercontent.com/piku/piku/master/piku.py && python3 ~/piku.py setup"
+
See INSTALL.md
+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
ConfigurationFYI 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
+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)`
+
Note
+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)
Before running piku
for the first time, you need to install the following Python packages at the system level:
sudo apt-get install git python3-virtualenv python3-pip
+sudo pip3 install -U click
+
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.
piku
user, Set up SSH accessSee INSTALL.md
+uWSGI can be installed in a variety of fashions. These instructions cover both pre-packaged and source installs depending on your system.
+++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
+
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.
++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
+
python3 piku.py setup
as outlined above before starting the service.
+++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
+
Warning
+These OS releases are no longer supported and these instructions are kept for reference purposes only.
+Warning
+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
+
++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
+
++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
+
++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
+
++This is EXPERIMENTAL and may not work at all.
+
++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.
+piku
user like such: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
+
GOPATH
and install godep
: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.
+ + + + + + + + + + + + + +Note
+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).
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.
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
+
piku
user, Set up SSH accessSee INSTALL.md
+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
Configurationpiku
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
+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
+
++ + + + + + + + + + + + + +This file was last updated on June 2019
+
Note
+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)
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
+
Note
+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.
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
+
piku
user, Set up SSH accessSee INSTALL.md
+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
Configurationpiku
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
+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
+
++ + + + + + + + + + + + + +This file was last updated on November 2018
+
Note
+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.
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
+
piku
user, Set up SSH accessSee INSTALL.md
+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
Configurationpiku
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
+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
+
++ + + + + + + + + + + + + +This file was last updated on November 2018
+
Warning
+These instructions are correct as of April 1st 2016. Quite a bit has changed since then in Raspberry Pi land, so you may need to adjust them accordingly.
+Start by flashing a SD card with the latest Raspbian Jessie Lite image.
+Boot it, launch raspi-config to perform (at least) the following configuration:
+# as 'pi' user
+sudo raspi-config
+
Optionally:
+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
+
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
+
(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
+
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
+
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 ;)
+ + + + + + + + + + + + + +To install it on your server, ssh
in as root
and run this:
curl https://piku.github.io/get | sh
+
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 main ways to install piku
on a server:
Use piku-bootstrap to do it if your server is already provisioned (that is what the TL;DR command does)
+Use cloud-init
to do it automatically at VPS build time (see the cloud-init
repository, which has examples for most common cloud providers)
Manually: Follow the guide below or one of the platform-specfic guides.
+There is also an Ansible playbook.
+Contributing
+If you are running piku
on specific Linux versions, feel free to contribute your own instructions.
piku
userpiku
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.
+
ssh
accessIf 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.
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.
+
To make life easier you can also install the piku
helper into your path (e.g. ~/bin
):
curl https://raw.githubusercontent.com/piku/piku/master/piku > ~/bin/piku && chmod 755 ~/bin/piku
+
This shell script simplifies working with multiple piku
remotes and applications:
cd
into a project folder that has a git
remote called piku
the helper will infer the remote server and app name and use them automatically:$ piku logs
+$ piku config:set MYVAR=12
+$ piku stop
+$ piku deploy
+$ piku destroy
+$ piku # <- show available remote and local commands
+
piku init
will download example Procfile
and ENV
files into the current folder:$ piku init
+Wrote ./ENV file.
+Wrote ./Procfile.
+
piku
helper also lets you pass settings to the underlying SSH command: -t
to run interactive commands remotely, and -A
to proxy authentication credentials in order to do remote git
pulls.For instance, here's how to use the -t
flag to obtain a bash
shell in the app directory of one of your piku
apps:
$ piku -t run bash
+Piku remote operator.
+Server: piku@cloud.mccormickit.com
+App: dashboard
+
+piku@piku:~/.piku/apps/dashboard$ ls
+data ENV index.html package.json package-lock.json Procfile server.wisp
+
Besides using the logs
command, there is a sample monitoring application to keep tabs on resource usage.
piku
, inspired by dokku
, allows you do git push
deployments to your own servers, no matter how small they are.
Installing Using/Features Managing and Monitoring Examples Web App Tutorial
"},{"location":"index.html#demo","title":"Demo","text":""},{"location":"index.html#workflow","title":"Workflow","text":"piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name: git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).Procfile
and starts matching worker processes.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file. You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
is considered STABLE. It is actively maintained, but \"actively\" here means the feature set is pretty much done, so it is only updated when new language runtimes are added or reproducible bugs crop up.
It currently requires Python 3.7 or above, since even though 3.8+ is now the baseline Python 3 version in Ubuntu LTS 20.04 and Debian 11 has already moved on to 3.9, there are no substantial differences between those versions.
"},{"location":"index.html#deprecation-notices","title":"Deprecation Notices","text":"Since most of its users run it on LTS distributions, there is no rush to introduce disruption. The current plan is to throw up a warning for older runtimes and do regression testing for 3.7-3.12 (replacing the current bracket of tests from 3.5 to 3.8), and make sure we also cover Ubuntu 22.04, Debian 11 and Fedora 37+.
"},{"location":"FAQ.html","title":"FAQ","text":"Q: Why piku
?
A: Partly because it's started out on the Raspberry Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because we knew the name would be cute and amusing.
Q: Why Python/why not Go?
A: We actually thought about doing this in Go right off the bat, but click is so cool and we needed to have uwsgi
running anyway, so we caved in. But possible future directions are likely to take something like suture and port this across (or just use Caddy), doing away with uwsgi
altogether.
Go also (at the time) did not have a way to vendor dependencies that we were 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 we eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since we wanted to make installing it on the Raspberry Pi as simple as possible.
Q: Why not just use dokku
?
A: We used dokku
daily for many projects. But it relied on a number of x64
containers that needed to be completely rebuilt for ARM
, and when we decided we 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 just starting to get herokuish
and buildstep
to build on ARM
.
piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name: git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).virtualenv
.GOPATH
for each app.package.json
into node_modules
.pom.xml
or build.gradle
file.leiningen
or the Clojure CLI and a deps.edn
file.bundle install
of your gems in an isolated folder.Procfile
and starts the relevant workers using uwsgi
as a generic process manager.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file.You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
has full virtual host support - i.e., you can host multiple apps on the same VPS and use DNS aliases to access them via different hostnames.
piku
will also set up either a private certificate or obtain one via Let's Encrypt to enable SSL.
If you are on a LAN and are accessing piku
from macOS/iOS/Linux clients, you can try using piku/avahi-aliases
to announce different hosts for the same IP address via Avahi/mDNS/Bonjour.
Besides static sites, piku
also supports directly mapping specific URL prefixes to filesystem paths (to serve static assets) or caching back-end responses (to remove load from applications).
These features are configured by setting appropriate values in the ENV
file.
piku
is intended to work in any POSIX-like environment where you have Python, nginx
, uwsgi
and ssh
: it has been deployed on Linux, FreeBSD, [Cygwin][cygwin] and the [Windows Subsystem for Linux][wsl].
As a baseline, it began its development on an original 256MB Rasbperry Pi Model B, and still runs reliably on it.
But its main use is as a micro-PaaS to run applications on cloud servers with both Intel and ARM CPUs, with either Debian or Ubuntu Linux as target platforms.
"},{"location":"features.html#supported-runtimes","title":"Supported Runtimes","text":"piku
currently supports apps written in Python, Node, Clojure, Java and a few other languages (like Go) in the works.
But as a general rule, if it can be invoked from a shell, it can be run inside piku
.
To make life easier you can also install the piku
helper into your path (e.g. ~/bin
):
curl https://raw.githubusercontent.com/piku/piku/master/piku > ~/bin/piku && chmod 755 ~/bin/piku\n
This shell script simplifies working with multiple piku
remotes and applications:
cd
into a project folder that has a git
remote called piku
the helper will infer the remote server and app name and use them automatically:$ piku logs\n$ piku config:set MYVAR=12\n$ piku stop\n$ piku deploy\n$ piku destroy\n$ piku # <- show available remote and local commands\n
piku init
will download example Procfile
and ENV
files into the current folder:$ piku init\nWrote ./ENV file.\nWrote ./Procfile.\n
piku
helper also lets you pass settings to the underlying SSH command: -t
to run interactive commands remotely, and -A
to proxy authentication credentials in order to do remote git
pulls.For instance, here's how to use the -t
flag to obtain a bash
shell in the app directory of one of your piku
apps:
$ piku -t run bash\nPiku remote operator.\nServer: piku@cloud.mccormickit.com\nApp: dashboard\n\npiku@piku:~/.piku/apps/dashboard$ ls\ndata ENV index.html package.json package-lock.json Procfile server.wisp\n
"},{"location":"manage.html#monitoring","title":"Monitoring","text":"Besides using the logs
command, there is a sample monitoring application to keep tabs on resource usage.
There is an active discussion forum for piku
where you can ask questions, share your deployments, and discuss new features, and we have a published roadmap.
Contributing Examples
"},{"location":"community/contributing.html","title":"Contributing","text":"piku
is a stable project, but we welcome contributions that:
piku
in various Linux distributions and environments (check the sister repositories in the project)By its very nature, piku
is a very small program. By today's standards of all-encompassing solutions this may seem strange, but it would benefit from being kept that way.
from os.path import abspath
PEP8
.So please keep that in mind when contributing.
For instance, if your runtime or framework needs additional setup, it might be better to contribute an utility script to run in a release
entry in the Procfile
rather than patching piku.py
--but do hack at it if that is the best way to achieve it.
Besides the bundled examples, there are a number of community-contributed examples that can be deployed using piku
.
They are meant to be illustrative of the kinds of applications that can be deployed using piku
, and are not meant to be exhaustive.
piku
apps, written in ClojureScriptA minimal piku
app has a root directory structure similar to this:
ENV\nProcfile\napp.py\nworker.py\nrequirements.txt\n
ENV Procfile
"},{"location":"configuration/index.html#configuration-files","title":"Configuration Files","text":"piku
relies on two configuration files shipped with your app to determine how to run it: ENV
and Procfile
.
ENV
file contains environment variables that allow you to configure both piku
and your app, following the 12-factor app approach.Procfile
tells piku
what kind of workers to runBesides ENV
and Procfile
, piku
also looks for runtime-specific files in the root of your app's directory:
requirements.txt
file at the top level, then the app is assumed to require Python.Gemfile
at the top level, then the app is assumed to require Ruby.package.json
file at the top level, then the app is assumed to require Node.js.pom.xml
or a build.gradle
file at the top level, then the app is assumed to require Java.deps.edn
or project.clj
file at the top level, then the app is assumed to require Clojure.Godeps
file at the top level, then the app is assumed to require Go.Info
go.mod
support is currently in development.
These are not exclusive, however. There is also a sample Phoenix app that demonstrates how to add support for additional runtimes.
"},{"location":"configuration/env.html","title":"ENV
Variables","text":"You can configure deployment settings by placing special variables in an ENV
file deployed with your app. This file should be placed in the root of your app's directory, and can look something like this:
# variables are global and can be replaced\nSETTING1=True\nSETTING2=${SETTING1}/Maybe\n\n# addr:port\nPORT=9080\nBIND_ADDRESS=0.0.0.0\n\n# the max number the worker will process\nRANGE=10\n\n# worker sleep interval between prints\nINTERVAL=1\n
"},{"location":"configuration/env.html#runtime-settings","title":"Runtime Settings","text":"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_VERSION
(int): Forces Python 3Warning
This is mostly deprecated (since piku
now runs solely on Python 3.x), but is kept around for legacy compatibility.
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.
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 connectionsUWSGI_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
pluginUWSGI_ASYNCIO
(integer): enable the Python 2/3 asyncio
plugin and set the number of tasksUWSGI_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","text":"NGINX_SERVER_NAME
: set the virtual host name associated with your appNGINX_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 IPsNGINX_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","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:
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 GBNGINX_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","text":"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_ROOT_CA
: set the certificate authority that Acme should use to generate public ssl certificates (string, default: letsencrypt.org
)Procfile
format","text":"piku
supports a Heroku-like Procfile
that you provide to indicate how to run one or more application processes (what Heroku calls \"dynos\"):
web: embedded_server --port $PORT\nworker: background_worker\n
"},{"location":"configuration/procfile.html#worker-types","title":"Worker Types","text":"piku
supports six different kinds of worker processes:
# A module to be loaded by uwsgi to serve HTTP requests\nwsgi: module.submodule:app\n# A background worker, using the default name\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
Each of these has slightly different features:"},{"location":"configuration/procfile.html#wsgi","title":"wsgi
","text":"wsgi
workers are Python-specific and must be specified in the format dotted.module:entry_point
. uwsgi
will load the specified module and call the entry_point
function to start the application, handling all the HTTP requests directly (your Python code will run the handlers, but will run as a part of the uwsgi
process).
uwsgi
will automatically spawn multiple workers for you, and you can control the number of workers via the UWSGI_PROCESSES
environment variable.
Also, in this mode uwsgi
will talk to nginx
via a Unix socket, so you don't need to worry about the HTTP server at all.
web
","text":"web
workers can be literally any executable that uwsgi
can run and that will serve HTTP requests. They must (by convention) honor the PORT
environment variable, so that the nginx
reverse proxy can talk to them.
worker
","text":"worker
processes are just standard processes that run in the background. They can actually have arbitrary names, and the idea is that they would perform any tasks your app requires that isn't directly related to serving web pages.
static
","text":"static
workers are simply a way to direct nginx
to mount the first argument as a static path and serve it directly. This is useful for serving (and caching) static files directly from your app, without having to go through application code.
Note
See nginx
caching for more information on how to configure nginx
to serve static files.
cron
","text":"A cron
worker is a process that runs at a specific time (or intervals), using a simplified crontab
expression preceding the command to be run (e.g. cron: */5 * * * * python batch.py
to run a batch every 5 minutes)
Warning
crontab
expressions are simplified and do not support ranges or lists, only single values, splits and *
(wildcard).
preflight
","text":"preflight
is a special \"worker\" that is run once before the app is deployed and dependencies are installed (can be useful for cleanups, like resetting caches, removing older versions of files, etc).
release
","text":"release
which is a special worker that is run once when the app is deployed, after installing dependencies (can be useful for build steps).
Any worker will be automatically respawned upon failure ([uWSGI][uwsgi] will automatically shun/throttle crashy workers).
"},{"location":"design/index.html","title":"Design","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.
git
, ssh
, uwsgi
, nginx
).Using uWSGI in emperor mode gives us the following features for free:
virtualenv
integrationuid
/gid
on a per-app basis (if necessary)An app is simply a git
repository with some additional files on the top level, the most important of which is the Procfile
.
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 configuration for a full list of environment variables that can also be set.
Environment variables can be changed after deployment using the config:set
command.
piku
follows a very simple set of rules to determine what kind of runtime is required, outlined in the configuration section
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).
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
).
This diagram outlines how its components interact:
graph TD\n subgraph \"systemd\"\n nginx([nginx])\n sshd([sshd])\n uwsgi([uwsgi])\n end\n uwsgi-->vassal([vassal])\n vassal-.->uwsgi.ini\n sshd-->piku([piku.py])-->repo[git repo]\n Procfile-->uwsgi.ini\n an-->app\n repo---app\n repo---ENV\n repo---requirements.txt\n repo---Procfile\n requirements.txt-->virtualenv\n uwsgi.ini-->virtualenv\n ENV-->an\n ENV-->uwsgi.ini\n nginx-.-mn[master<br>nginx.conf]\n mn-.-an[app<br>nginx.conf]
"},{"location":"design/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":"install/index.html","title":"Installation","text":""},{"location":"install/index.html#tldr","title":"TL;DR:","text":"To install it on your server, ssh
in as root
and run this:
curl https://piku.github.io/get | sh\n
"},{"location":"install/index.html#installation-methods","title":"Installation Methods","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 main ways to install piku
on a server:
Use piku-bootstrap to do it if your server is already provisioned (that is what the TL;DR command does)
Use cloud-init
to do it automatically at VPS build time (see the cloud-init
repository, which has examples for most common cloud providers)
Manually: Follow the guide below or one of the platform-specfic guides.
There is also an Ansible playbook.
Contributing
If you are running piku
on specific Linux versions, feel free to contribute your own instructions.
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/index.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.
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":"install/INSTALL-centos-9.html","title":"Installation on CentOS 9","text":"Note
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/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/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/INSTALL-centos-9.html#set-up-ssh-access","title":"Set up SSH access","text":"See INSTALL.md
"},{"location":"install/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/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/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/INSTALL-centos-9.html#notes","title":"Notes","text":""},{"location":"install/INSTALL-other.html","title":"Installation on other platforms","text":"Note
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)
Before running piku
for the first time, you need to install the following Python packages at the system level:
sudo apt-get install git python3-virtualenv python3-pip\nsudo pip3 install -U click\n
"},{"location":"install/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.
piku
user, Set up SSH access","text":"See INSTALL.md
"},{"location":"install/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/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.
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/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/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.
Warning
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/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/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/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/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/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.
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
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/INSTALL-raspbian-9.4-stretch-10-buster.html","title":"Installation on Raspbian Stretch or Buster","text":"Note
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).
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.
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/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/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/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/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/INSTALL-raspbian-9.4-stretch-10-buster.html#notes","title":"Notes","text":"This file was last updated on June 2019
"},{"location":"install/INSTALL-ubuntu-16.04.html","title":"Ubuntu 16.04","text":"Note
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)
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
"},{"location":"install/INSTALL-ubuntu-18.04-bionic.html","title":"Installation on Ubuntu 18.04 LTS (Bionic)","text":"Note
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.
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/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/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/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/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/INSTALL-ubuntu-18.04-bionic.html#notes","title":"Notes","text":"This file was last updated on November 2018
"},{"location":"install/INSTALL-ubuntu-22.04-jammy.html","title":"Installation on Ubuntu 22.04 LTS (Jammy)","text":"Note
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.
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/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/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/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/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/INSTALL-ubuntu-22.04-jammy.html#notes","title":"Notes","text":"This file was last updated on November 2018
"},{"location":"install/RASPBERRY_PI_QUICKSTART.html","title":"Setting up a Raspberry Pi Piku Server from Scratch","text":"Warning
These instructions are correct as of April 1st 2016. Quite a bit has changed since then in Raspberry Pi land, so you may need to adjust them accordingly.
Start by flashing a SD card with the latest Raspbian Jessie Lite image.
"},{"location":"install/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:
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":"install/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
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\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":"install/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
If you're still here, odds are your Pi is ready for work"},{"location":"install/RASPBERRY_PI_QUICKSTART.html#testing","title":"Testing","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 ;)
"}]} \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..2ea9bca --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"index.html","title":"Home","text":"piku
, inspired by dokku
, allows you do git push
deployments to your own servers, no matter how small they are.
Installing Using/Features Managing and Monitoring Examples Web App Tutorial
"},{"location":"index.html#demo","title":"Demo","text":""},{"location":"index.html#workflow","title":"Workflow","text":"piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name: git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).Procfile
and starts matching worker processes.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file. You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
is considered STABLE. It is actively maintained, but \"actively\" here means the feature set is pretty much done, so it is only updated when new language runtimes are added or reproducible bugs crop up.
It currently requires Python 3.7 or above, since even though 3.8+ is now the baseline Python 3 version in Ubuntu LTS 20.04 and Debian 11 has already moved on to 3.9, there are no substantial differences between those versions.
"},{"location":"index.html#deprecation-notices","title":"Deprecation Notices","text":"Since most of its users run it on LTS distributions, there is no rush to introduce disruption. The current plan is to throw up a warning for older runtimes and do regression testing for 3.7-3.12 (replacing the current bracket of tests from 3.5 to 3.8), and make sure we also cover Ubuntu 22.04, Debian 11 and Fedora 37+.
"},{"location":"FAQ.html","title":"FAQ","text":"Q: Why piku
?
A: Partly because it's started out on the Raspberry Pi, because it's Japanese onomatopeia for 'twitch' or 'jolt', and because we knew the name would be cute and amusing.
Q: Why Python/why not Go?
A: We actually thought about doing this in Go right off the bat, but click is so cool and we needed to have uwsgi
running anyway, so we caved in. But possible future directions are likely to take something like suture and port this across (or just use Caddy), doing away with uwsgi
altogether.
Go also (at the time) did not have a way to vendor dependencies that we were 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 we eventually switched over to 3.5 once it was supported in Debian Stretch and Raspbian since we wanted to make installing it on the Raspberry Pi as simple as possible.
Q: Why not just use dokku
?
A: We used dokku
daily for many projects. But it relied on a number of x64
containers that needed to be completely rebuilt for ARM
, and when we decided we 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 just starting to get herokuish
and buildstep
to build on ARM
.
piku
supports a Heroku-like workflow:
git
SSH remote pointing to your piku
server with the app name as repo name: git remote add piku piku@yourserver:appname
.git push piku master
(or if you want to push a different branch than the current one use git push piku release-branch-name
).piku
determines the runtime and installs the dependencies for your app (building whatever's required).virtualenv
.GOPATH
for each app.package.json
into node_modules
.pom.xml
or build.gradle
file.leiningen
or the Clojure CLI and a deps.edn
file.bundle install
of your gems in an isolated folder.Procfile
and starts the relevant workers using uwsgi
as a generic process manager.release
worker which is run once when the app is deployed.config:set
) or scale up/down worker processes (ps:scale
).nginx
settings into an ENV
configuration file.You can also deploy a gh-pages
style static site using a static
worker type, with the root path as the argument, and run a release
task to do some processing on the server after git push
.
piku
has full virtual host support - i.e., you can host multiple apps on the same VPS and use DNS aliases to access them via different hostnames.
piku
will also set up either a private certificate or obtain one via Let's Encrypt to enable SSL.
If you are on a LAN and are accessing piku
from macOS/iOS/Linux clients, you can try using piku/avahi-aliases
to announce different hosts for the same IP address via Avahi/mDNS/Bonjour.
Besides static sites, piku
also supports directly mapping specific URL prefixes to filesystem paths (to serve static assets) or caching back-end responses (to remove load from applications).
These features are configured by setting appropriate values in the ENV
file.
piku
is intended to work in any POSIX-like environment where you have Python, nginx
, uwsgi
and ssh
: it has been deployed on Linux, FreeBSD, [Cygwin][cygwin] and the [Windows Subsystem for Linux][wsl].
As a baseline, it began its development on an original 256MB Rasbperry Pi Model B, and still runs reliably on it.
But its main use is as a micro-PaaS to run applications on cloud servers with both Intel and ARM CPUs, with either Debian or Ubuntu Linux as target platforms.
"},{"location":"features.html#supported-runtimes","title":"Supported Runtimes","text":"piku
currently supports apps written in Python, Node, Clojure, Java and a few other languages (like Go) in the works.
But as a general rule, if it can be invoked from a shell, it can be run inside piku
.
To make life easier you can also install the piku
helper into your path (e.g. ~/bin
):
curl https://raw.githubusercontent.com/piku/piku/master/piku > ~/bin/piku && chmod 755 ~/bin/piku\n
This shell script simplifies working with multiple piku
remotes and applications:
cd
into a project folder that has a git
remote called piku
the helper will infer the remote server and app name and use them automatically:$ piku logs\n$ piku config:set MYVAR=12\n$ piku stop\n$ piku deploy\n$ piku destroy\n$ piku # <- show available remote and local commands\n
piku init
will download example Procfile
and ENV
files into the current folder:$ piku init\nWrote ./ENV file.\nWrote ./Procfile.\n
piku
helper also lets you pass settings to the underlying SSH command: -t
to run interactive commands remotely, and -A
to proxy authentication credentials in order to do remote git
pulls.For instance, here's how to use the -t
flag to obtain a bash
shell in the app directory of one of your piku
apps:
$ piku -t run bash\nPiku remote operator.\nServer: piku@cloud.mccormickit.com\nApp: dashboard\n\npiku@piku:~/.piku/apps/dashboard$ ls\ndata ENV index.html package.json package-lock.json Procfile server.wisp\n
"},{"location":"manage.html#monitoring","title":"Monitoring","text":"Besides using the logs
command, there is a sample monitoring application to keep tabs on resource usage.
There is an active discussion forum for piku
where you can ask questions, share your deployments, and discuss new features, and we have a published roadmap.
Contributing Examples
"},{"location":"community/contributing.html","title":"Contributing","text":"piku
is a stable project, but we welcome contributions that:
piku
in various Linux distributions and environments (check the sister repositories in the project)By its very nature, piku
is a very small program. By today's standards of all-encompassing solutions this may seem strange, but it would benefit from being kept that way.
from os.path import abspath
PEP8
.So please keep that in mind when contributing.
For instance, if your runtime or framework needs additional setup, it might be better to contribute an utility script to run in a release
entry in the Procfile
rather than patching piku.py
--but do hack at it if that is the best way to achieve it.
Besides the bundled examples, there are a number of community-contributed examples that can be deployed using piku
.
They are meant to be illustrative of the kinds of applications that can be deployed using piku
, and are not meant to be exhaustive.
piku
apps, written in ClojureScriptA minimal piku
app has a root directory structure similar to this:
ENV\nProcfile\napp.py\nworker.py\nrequirements.txt\n
ENV Procfile
"},{"location":"configuration/index.html#configuration-files","title":"Configuration Files","text":"piku
relies on two configuration files shipped with your app to determine how to run it: ENV
and Procfile
.
ENV
file contains environment variables that allow you to configure both piku
and your app, following the 12-factor app approach.Procfile
tells piku
what kind of workers to runBesides ENV
and Procfile
, piku
also looks for runtime-specific files in the root of your app's directory:
requirements.txt
file at the top level, then the app is assumed to require Python.Gemfile
at the top level, then the app is assumed to require Ruby.package.json
file at the top level, then the app is assumed to require Node.js.pom.xml
or a build.gradle
file at the top level, then the app is assumed to require Java.deps.edn
or project.clj
file at the top level, then the app is assumed to require Clojure.Godeps
file at the top level, then the app is assumed to require Go.Info
go.mod
support is currently in development.
These are not exclusive, however. There is also a sample Phoenix app that demonstrates how to add support for additional runtimes.
"},{"location":"configuration/env.html","title":"ENV
Variables","text":"You can configure deployment settings by placing special variables in an ENV
file deployed with your app. This file should be placed in the root of your app's directory, and can look something like this:
# variables are global and can be replaced\nSETTING1=True\nSETTING2=${SETTING1}/Maybe\n\n# addr:port\nPORT=9080\nBIND_ADDRESS=0.0.0.0\n\n# the max number the worker will process\nRANGE=10\n\n# worker sleep interval between prints\nINTERVAL=1\n
"},{"location":"configuration/env.html#runtime-settings","title":"Runtime Settings","text":"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_VERSION
(int): Forces Python 3Warning
This is mostly deprecated (since piku
now runs solely on Python 3.x), but is kept around for legacy compatibility.
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.
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 connectionsUWSGI_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
pluginUWSGI_ASYNCIO
(integer): enable the Python 2/3 asyncio
plugin and set the number of tasksUWSGI_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","text":"NGINX_SERVER_NAME
: set the virtual host name associated with your appNGINX_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 IPsNGINX_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","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:
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 GBNGINX_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","text":"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_ROOT_CA
: set the certificate authority that Acme should use to generate public ssl certificates (string, default: letsencrypt.org
)Procfile
format","text":"piku
supports a Heroku-like Procfile
that you provide to indicate how to run one or more application processes (what Heroku calls \"dynos\"):
web: embedded_server --port $PORT\nworker: background_worker\n
"},{"location":"configuration/procfile.html#worker-types","title":"Worker Types","text":"piku
supports six different kinds of worker processes:
# A module to be loaded by uwsgi to serve HTTP requests\nwsgi: module.submodule:app\n# A background worker, using the default name\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
Each of these has slightly different features:"},{"location":"configuration/procfile.html#wsgi","title":"wsgi
","text":"wsgi
workers are Python-specific and must be specified in the format dotted.module:entry_point
. uwsgi
will load the specified module and call the entry_point
function to start the application, handling all the HTTP requests directly (your Python code will run the handlers, but will run as a part of the uwsgi
process).
uwsgi
will automatically spawn multiple workers for you, and you can control the number of workers via the UWSGI_PROCESSES
environment variable.
Also, in this mode uwsgi
will talk to nginx
via a Unix socket, so you don't need to worry about the HTTP server at all.
web
","text":"web
workers can be literally any executable that uwsgi
can run and that will serve HTTP requests. They must (by convention) honor the PORT
environment variable, so that the nginx
reverse proxy can talk to them.
worker
","text":"worker
processes are just standard processes that run in the background. They can actually have arbitrary names, and the idea is that they would perform any tasks your app requires that isn't directly related to serving web pages.
static
","text":"static
workers are simply a way to direct nginx
to mount the first argument as a static path and serve it directly. This is useful for serving (and caching) static files directly from your app, without having to go through application code.
Note
See nginx
caching for more information on how to configure nginx
to serve static files.
cron
","text":"A cron
worker is a process that runs at a specific time (or intervals), using a simplified crontab
expression preceding the command to be run (e.g. cron: */5 * * * * python batch.py
to run a batch every 5 minutes)
Warning
crontab
expressions are simplified and do not support ranges or lists, only single values, splits and *
(wildcard).
preflight
","text":"preflight
is a special \"worker\" that is run once before the app is deployed and dependencies are installed (can be useful for cleanups, like resetting caches, removing older versions of files, etc).
release
","text":"release
which is a special worker that is run once when the app is deployed, after installing dependencies (can be useful for build steps).
Any worker will be automatically respawned upon failure ([uWSGI][uwsgi] will automatically shun/throttle crashy workers).
"},{"location":"design/index.html","title":"Design","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.
git
, ssh
, uwsgi
, nginx
).Using uWSGI in emperor mode gives us the following features for free:
virtualenv
integrationuid
/gid
on a per-app basis (if necessary)An app is simply a git
repository with some additional files on the top level, the most important of which is the Procfile
.
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 configuration for a full list of environment variables that can also be set.
Environment variables can be changed after deployment using the config:set
command.
piku
follows a very simple set of rules to determine what kind of runtime is required, outlined in the configuration section
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).
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
).
This diagram outlines how its components interact:
graph TD\n subgraph \"systemd\"\n nginx([nginx])\n sshd([sshd])\n uwsgi([uwsgi])\n end\n uwsgi-->vassal([vassal])\n vassal-.->uwsgi.ini\n sshd-->piku([piku.py])-->repo[git repo]\n Procfile-->uwsgi.ini\n an-->app\n repo---app\n repo---ENV\n repo---requirements.txt\n repo---Procfile\n requirements.txt-->virtualenv\n uwsgi.ini-->virtualenv\n ENV-->an\n ENV-->uwsgi.ini\n nginx-.-mn[master<br>nginx.conf]\n mn-.-an[app<br>nginx.conf]
"},{"location":"design/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":"install/index.html","title":"Installation","text":""},{"location":"install/index.html#tldr","title":"TL;DR:","text":"To install it on your server, ssh
in as root
and run this:
curl https://piku.github.io/get | sh\n
"},{"location":"install/index.html#installation-methods","title":"Installation Methods","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 main ways to install piku
on a server:
Use piku-bootstrap to do it if your server is already provisioned (that is what the TL;DR command does)
Use cloud-init
to do it automatically at VPS build time (see the cloud-init
repository, which has examples for most common cloud providers)
Manually: Follow the guide below or one of the platform-specfic guides.
There is also an Ansible playbook.
Contributing
If you are running piku
on specific Linux versions, feel free to contribute your own instructions.
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/index.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.
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":"install/INSTALL-centos-9.html","title":"Installation on CentOS 9","text":"Note
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/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/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/INSTALL-centos-9.html#set-up-ssh-access","title":"Set up SSH access","text":"See INSTALL.md
"},{"location":"install/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/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/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/INSTALL-centos-9.html#notes","title":"Notes","text":""},{"location":"install/INSTALL-other.html","title":"Installation on other platforms","text":"Note
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)
Before running piku
for the first time, you need to install the following Python packages at the system level:
sudo apt-get install git python3-virtualenv python3-pip\nsudo pip3 install -U click\n
"},{"location":"install/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.
piku
user, Set up SSH access","text":"See INSTALL.md
"},{"location":"install/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/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.
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/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/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.
Warning
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/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/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/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/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/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.
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
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/INSTALL-raspbian-9.4-stretch-10-buster.html","title":"Installation on Raspbian Stretch or Buster","text":"Note
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).
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.
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/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/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/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/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/INSTALL-raspbian-9.4-stretch-10-buster.html#notes","title":"Notes","text":"This file was last updated on June 2019
"},{"location":"install/INSTALL-ubuntu-16.04.html","title":"Ubuntu 16.04","text":"Note
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)
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
"},{"location":"install/INSTALL-ubuntu-18.04-bionic.html","title":"Installation on Ubuntu 18.04 LTS (Bionic)","text":"Note
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.
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/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/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/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/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/INSTALL-ubuntu-18.04-bionic.html#notes","title":"Notes","text":"This file was last updated on November 2018
"},{"location":"install/INSTALL-ubuntu-22.04-jammy.html","title":"Installation on Ubuntu 22.04 LTS (Jammy)","text":"Note
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.
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/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/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/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/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/INSTALL-ubuntu-22.04-jammy.html#notes","title":"Notes","text":"This file was last updated on November 2018
"},{"location":"install/RASPBERRY_PI_QUICKSTART.html","title":"Setting up a Raspberry Pi Piku Server from Scratch","text":"Warning
These instructions are correct as of April 1st 2016. Quite a bit has changed since then in Raspberry Pi land, so you may need to adjust them accordingly.
Start by flashing a SD card with the latest Raspbian Jessie Lite image.
"},{"location":"install/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:
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":"install/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
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\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":"install/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
If you're still here, odds are your Pi is ready for work"},{"location":"install/RASPBERRY_PI_QUICKSTART.html#testing","title":"Testing","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 ;)
"}]} \ 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 @@ + +