=================================
Store Production Install (Docker)
=================================
The App Store can be installed using `Docker `_. This is still work in progress and therefore not recommended for production.
Benefits and Drawbacks
======================
Docker is just another technology with its own upsides and downsides. Make an educated decision on whether you want to use it or go for an alternative.
**Benefits**:
* No need to install development libraries on your server (e.g. C compiler, Node.js)
* No need to install a specific Python version
* No need to manually run update commands. Just download a new container version and start it
* Ability to run any operating system that supports your required Docker features
* Faster deployment because Python libraries, JavaScript libraries and translations come pre-built
* Easier backups since code is completely split from production data and configuration
**Drawbacks**:
* Knowledge of docker-compose required to change and optimize deployment
* Docker daemon `must run as root `_
* Python bugfixes and security updates are not available through your package manager; they require a container rebuild and deployment
* Much more complex setup due to another layer of abstraction
General Information
===================
This page will detail a setup with the following configuration
* the host runs Ubuntu 16.04
* PostgreSQL and Nginx are run on the host
If you want to run a different setup you need to provide your own **docker-compose.yml** and adjust your settings accordingly.
Building the Image
==================
To build the Docker image install Git, Docker and docker-compose on your development machine, e.g.::
sudo apt-get install docker docker-compose git
and start the daemon::
sudo systemctl enable docker
sudo systemctl restart docker
Then clone the repository and build the image::
git clone https://github.com/nextcloud/appstore
cd appstore
git checkout tags/VERSION
sudo docker-compose build production
Export your container to be able to upload it to your production server::
sudo docker save -o nextcloudappstore.tar.gz appstore_production
.. note:: Docker Hub integration would be nice
Deploying the Image
===================
Upload the **nextcloudappstore.tar.gz** archive onto your production server.
Initial Setup
=============
These steps are only required for your initial setup.
Install Docker and docker-compose on your production server, e.g.::
sudo apt-get install docker docker-compose
and start the daemon::
sudo systemctl enable docker
sudo systemctl restart docker
Then create and change into your target installation directory, e.g.::
sudo mkdir -p /srv
cd /srv
and create a **config/** folder which is going to hold your App Store configuration files::
sudo mkdir -p config/
Next create empty files inside the config folder::
sudo touch config/__init__.py
sudo touch config/production.py
sudo touch config/uwsgi.ini
sudo touch config/newrelic.ini # only needed if you run New Relic
Configuring uWSGI
-----------------
uWSGI is a multi language app server which will be used to run the App Store's Python code inside the container. In addition to uWSGI you will need to configure an additional web-server. A web-server is required to:
* serve static files to the client (e.g. CSS, JavaScript, images)
* encrypt the traffic with TLS
* redirect incoming requests to uWSGI
The following config file represents a minimal `uwsgi config `_
.. code-block:: ini
[uwsgi]
chdir = /srv
wsgi-file = /srv/nextcloudappstore/wsgi.py
master = true
processes = 10
vacuum = true
uid = nextcloudappstore
gid = nextcloudappstore
socket = 0.0.0.0:8000
If your server does not support the uWSGI protocol natively, replace **socket** with::
http = 0.0.0.0:8000
You may also want to configure statistics and adjust threads/processes to whatever works best on your server. Consult the `documentation `_ for more information.
Configuring The App Store
-------------------------
The **production.py** contains all App Store specific settings that you may want to adjust. For a basic configuration take a look at :ref:`an example production configuration `
Setting Up Your Database
------------------------
Install PostgreSQL on your host machine::
sudo apt-get install postgresql
To allow the container to connect to it open **/etc/postgresql/9.5/main/postgresql.conf** and modify/add the following section::
listen_addresses = '127.0.0.1,172.17.0.1'
Then whitelist your container IP in **/etc/postgresql/9.5/main/pg_hba.conf**::
host nextcloudappstore nextcloudappstore 172.17.0.2/32 md5
.. note:: This expects the database user and database to be named **nextcloudappstore**, your container IP to be **172.17.0.2** and host to run on **172.17.0.1**
Then enable and start it::
sudo systemctl enable postgresql.service
sudo systemctl restart postgresql.service
and create a user and database::
sudo -s
su - postgres
psql
CREATE USER nextcloudappstore WITH PASSWORD 'password';
CREATE DATABASE nextcloudappstore OWNER nextcloudappstore;
\q
exit
.. note:: Use your own password instead of the password example!
Configuring Your Web-Server
---------------------------
First install nginx::
sudo apt-get install nginx
Then create a new configuration for it in **/etc/nginx/sites-available/nextcloudappstore**:
.. code-block:: nginx
upstream nextcloudappstore {
server 127.0.0.1:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name apps.nextcloud.com;
charset utf-8;
# replace this with your ssl certificates
ssl_certificate /etc/nginx/ssl/nextcloudappstore.crt;
ssl_certificate_key /etc/nginx/ssl/nextcloudappstore.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/private/ca-certs.pem;
add_header Strict-Transport-Security max-age=15768000;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
client_max_body_size 75M;
location /media {
alias /srv/media;
}
location /static {
alias /srv/static;
}
location / {
uwsgi_pass nextcloudappstore;
include uwsgi_params;
}
}
Finally replace your default configuration::
sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/nextcloudappstore /etc/nginx/sites-enabled/default
sudo systemctl enable nginx
sudo systemctl restart nginx
Configuring New Relic (Optional)
--------------------------------
TBD
Creating Docker-Compose Configuration
-------------------------------------
Either create your own configuration or grab a copy of our `docker-compose.yml `_ and modify it if necessary. Place the file in your designated directory::
cd /srv
sudo wget https://raw.githubusercontent.com/nextcloud/appstore/master/docker-compose.yml
Starting the Image
------------------
First load the latest uploaded image::
sudo docker load -i /path/to/nextcloudappstore.tar.gz
Then change into your server directory and start the container::
cd /srv
sudo docker-compose up production
The following directories will be created initially:
* **static**: holds read only files which need to be served by your web-server
* **media**: holds user uploaded files
* **logs**: contains your log file
The **static** directory will be populated with static files when a container is started and all database migrations and fixtures will be imported.
Creating an Admin User
----------------------
To create the initial admin user and verify his email, run the following command::
sudo docker-compose exec production python manage.py createsuperuser --username admin --email admin@admin.com
sudo docker-compose exec production python manage.py verifyemail --username admin --email admin@admin.com
The first command will ask for the password.
Configure Social Logins
-----------------------
Once the App Store is up and running social login needs to be configured. The App Store uses `django-allauth `_ for local and social login. In order to configure these logins, most providers require you to register your app beforehand.
**GitHub**
GitHub is currently the only supported social login. In order to register the App Store, go to `your application settings page `_ and enter the following details:
* **Application name**: Nextcloud App Store
* **Homepage URL**: https://apps.nextcloud.com
* **Authorization callback URL**: https://apps.nextcloud.com/github/login/callback/
Afterwards your **client id** and **client secret** are displayed. These need to be saved inside the database. To do that, either log into the admin interface, change your site's domain and add GitHub as a new social application or run the following command::
sudo docker-compose exec python manage.py setupsocial --github-client-id "CLIENT_ID" --github-secret "SECRET" --domain apps.nextcloud.com
.. note:: The above mentioned domains need to be changed if you want to run the App Store on a different server.
.. note:: For local testing use localhost:8000 as domain name. Furthermore the confirmation mail will also be printed in your shell that was used to start the development server.
.. _prod_install_release_sync_docker:
Sync Nextcloud Releases from GitHub
-----------------------------------
The App Store needs to know about Nextcloud versions because:
* app releases are grouped by app version on the app detail page
* you can :ref:`access a REST API to get all available versions `
Before **3.2.0** releases were imported either manually or via the a shipped JSON file. This process proved to be very tedious. In **3.2.0** a command was introduced to sync releases (git tags) directly from GitHub.
You can run the command by giving it the oldest supported Nextcloud version::
sudo docker-compose exec python manage.py syncnextcloudreleases --oldest-supported="12.0.0"
All existing versions prior to this release will be marked as not having a release, new versions will be imported and the latest version will be marked as current version.
You can also do a test run and see what kind of versions would be imported::
sudo docker-compose exec python manage.py syncnextcloudreleases --oldest-supported="12.0.0" --print
The GitHub API is rate limited to 60 requests per second. Depending on how far back your **oldest-supported** version goes a single command might fetch multiple pages of releases. If you want to run the command more than 10 times per hour it is recommended to `obtain and configure a GitHub OAuth2 token `_.
After obtaining the token from GitHub, add it anywhere in your settings file (**production.py**), e.g.:
.. code-block:: python
GITHUB_API_TOKEN = '4bab6b3dfeds8857371a48855d3e87d38d4b7e65'
To automate syncing you might want to add the command as a cronjob and schedule it every hour.
.. note:: Only one sync command should be run at a time, otherwise race conditions might cause unpredictable results. To ensure this use a proper cronjob daemon that supports running only one command at a time, for instance `SystemD timers `_