Bare Metal Deployment with systemd

Introduction

This guide describes an installation of Infinite Scale as a systemd service on bare metal. This ranges from a small installation on a Raspberry Pi up to installations on a decent server.

Note that this guide expects that prerequisite of a computer with an installed Linux distribution of choice is met and required software other than Infinite Scale is installed and preconfigured. There is no detailed explanation but, where possible, links for more information are provided.

This guide was tested on a Debian 11 (bullseye) host but should work on any other modern Linux system with systemd.

The embedded IDM service provides a minimal LDAP service for Infinite Scale and does not replace a LDAP server. See the IDM Service Configuration for details.
Consider to extend the configuration described based on the information given in Graceful Shutdown.

Requirements

  • A supported filesystem according the ocis prerequisites.

  • systemd

  • A HTTP reverse proxy, there are examples using nginx and Apache

  • Certbot + the nginx or Apache plugin

    • For certbot, there are many command line options available supporting common tasks like increasing security measures or automatic redirection, the example commands are limited to the minimum issuing a certificate. This includes that configuration files and security measures need to be applied manually.

    • With respect to security, some of the measures are shown in examples but not all possibilities are covered.

    • If using certbot command line options, files may be split by port and content can differ, though the result when combined is the same.

Excluded Tasks

There are a few steps that are recommended but not covered in this guide:

  • Automate the Let’s Encrypt certificate renewal via cron jobs

  • Install and set up a firewall

Used Settings

The following settings were used in this guide. You can change this according your needs:

  • The Infinite Scale binary location: /usr/local/bin (OS default)

  • The Infinite Scale configuration directory: /etc/ocis

  • The Infinite Scale data directory: /var/lib/ocis

  • The URL accessing Infinite Scale: ocis.example.com
    Note that this URL must resolve to the server running this installation.

  • The internal port accessing Infinite Scale: 9200 (default)

Install and Prepare Infinite Scale

Install and configure the Infinite Scale Binary

Download and install the Infinite Scale binary. To get the stable binary from ownCloud, visit download.owncloud.com, select the version and the platform of choice and copy the link of the file.

sudo wget -O /usr/local/bin/ocis <file_url>

Make the binary executable with:

sudo chmod +x /usr/local/bin/ocis

Check the version installed:

ocis version  --skip-services

The output looks like this:

Version: 5.0.2
Compiled: 2024-04-17 00:00:00 +0000 UTC

Create a Service User

In your operating system, create a user and group who will run the ocis service and own all the files of the Infinite Scale service but is not allowed to log in, has no shell and no home directory.

sudo useradd --system --no-create-home --shell=/sbin/nologin ocis

Infinite Scale Data Directory

Create the ocis data directory. All system data will be stored here including all files uploaded by the users.

sudo mkdir -p /var/lib/ocis

Make the service user ocis the owner of the data directory.

sudo chown ocis:ocis /var/lib/ocis

Infinite Scale Configuration File

Create a directory and config file necessary for ocis. For security reasons, this user should have restricted permissions for this directory:

sudo mkdir -p /etc/ocis
sudo touch /etc/ocis/ocis.env
sudo chown -R ocis:ocis /etc/ocis

Create the environment file /etc/ocis/ocis.env with the following content. Adjust the OCIS_URL variable to hold your domain where Infinite Scale will be reachable via nginx. Add the correct port to OCIS_URL if it deviates from the default port 443 like https://ocis.example.com:4242. See the General Information section for more information about the environment variables used.

Setting the correct OCIS_URL is essential for the built-in openIDConnect IDP as the IDP service needs to be reachable under the same host and port as the reverse proxy is configured. If this has not been configured the same, the IDP service will log errors like origin does not match request URL. See the Using the Embedded IDP Service for configuration notes of the PROXY_TLS environment variable.

See the important notes for Configurations to Access the Web UI.
sudo vi /etc/ocis/ocis.env
OCIS_URL=https://ocis.example.com
PROXY_HTTP_ADDR=0.0.0.0:9200
PROXY_TLS=false
OCIS_INSECURE=false

OCIS_LOG_LEVEL=warn

OCIS_CONFIG_DIR=/etc/ocis
OCIS_BASE_DATA_PATH=/var/lib/ocis

PROXY_TLS is set to false because TLS termination will be done by the webserver. Though you also can secure the communication between Infinite Scale and the webserver, this is not covered by this document.

Generate the initial Infinite Scale configuration file, also see The ocis init Command:

sudo -u ocis ocis init --config-path /etc/ocis

You will be asked if you want to configure Ininite Scale with certificate checking disabled. You can safely answer yes. Infinite Scale is composed of several microservices which encrypt the communication between them with TLS. By answering with yes the communication is still encrypted but client and server certificates aren’t checked for validity. Usually this is good enough. For an extra secure deployment, provide a verifiable TLS certificate and enable certificate checking.

The command when run successfully will show you the initial admin user’s password. Write it down somewhere safe so that you can log in when the setup is complete. The password can be changed in the UI later on or be reset if forgotten via Password Reset for the Admin User.

This command will create the configuration file /etc/ocis/ocis.yaml.

Do NOT delete the ocis.yaml file without creating a backup of it first. When you regenerate the ocis.yaml file, it will be out of sync with the stored user data in the ocis data directory /var/lib/ocis. If for some reason you still want to regenerate the config file, you first need to empty the data directory but beware if you already have user files stored there. Also see The ocis init Command for more details.

Setup the systemd Service

To run the Infinite Scale runtime as a systemd service, create the file /etc/systemd/system/ocis.service with the content provided below. The easiest way to do this is with the following command:

sudo systemctl edit --force --full ocis.service

Then copy the content of the systemd file below into the editor and save it. ocis_bin

systemd file
[Unit]
Description=OCIS server

[Service]
Type=simple
User=ocis
Group=ocis
EnvironmentFile=/etc/ocis/ocis.env
ExecStart=/usr/local/bin/ocis server
Restart=always

[Install]
WantedBy=multi-user.target

Run the following command to apply your changes:

sudo systemctl daemon-reload

Now you can run Infinite Scale as a systemd service. Start it with:

sudo systemctl enable --now ocis

With this setup, Infinite Scale is also restarted automatically after a reboot.

If you need to restart Infinite Scale because of configuration changes in /etc/ocis/ocis.env, run:

sudo systemctl restart ocis

The systemd logs of Infinite Scale can be displayed by issuing:

sudo journalctl -f -u ocis

Dependent Infinite Scale Service Startup

If you want to ensure that you have a necessary service like a NFS mount point up and running before the Infinite Scale service starts up, see Start a Service After a Resource is Mounted.

This step can be an important measure, because if the Infinite Scale service starts up but the necessary mount point is not available, you may be in an undefined Infinite Scale operating state.

Nginx as Reverse Proxy

Whenever a configuration change has been made, you need to do a configuration check and reload the nginx configuration. This can be done with two methods as described below. Select your preferred one. For ease of writing, the examples show sudo nginx -s reload.
  • sudo nginx -s reload

    Note that this command includes checking and reloading the config in the same step.

  • sudo nginx -t
    sudo systemctl reload nginx

    Note that using systemctl reload nginx alone will NOT validate your configuration but will execute the command in a clean environment and not in the current user environment.

Prepare nginx for certbot

To set up nginx as a reverse proxy with Let’s Encrypt TLS certificates, create a file called e.g. ocis under /etc/nginx/sites-available with the following content:

server {
        listen 80 ;
        listen [::]:80 ;

        server_name ocis.example.com;
}
  • Activate the new nginx config:

    sudo ln -s /etc/nginx/sites-available/ocis /etc/nginx/sites-enabled/ocis
  • Check the config and reload nginx:

    sudo nginx -s reload

Issuing a Certificate via certbot for nginx

Run certbot to issue the TLS certificates:

sudo certbot --nginx -d ocis.example.com

Finalize the nginx Configuration

Adapt the config to redirect automatically to https, use the newly generated certificates and add the required proxy configuration. The full config should look like this:

server {
        listen 80 ;
        listen [::]:80 ;

        server_name ocis.example.com;

        # location to redirect to https
        location / {
            # add port if deviates via OCIS_URL
            return 301 https://$server_name$request_uri;
        }
}

server {
        # default 443 but can deviate if set in OCIS_URL
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name ocis.example.com;

        # certificates managed by Certbot
        ssl_certificate /etc/letsencrypt/live/ocis.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/ocis.example.com/privkey.pem;

        # options and dhparams managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
            # OIDC Tokens in headers are quite large and can exceed default limits of reverse proxies
            proxy_buffers 4 256k;
            proxy_buffer_size 128k;
            proxy_busy_buffers_size 256k;

            # Disable checking of client request body size
            client_max_body_size 0;

            proxy_pass http://localhost:9200;
            proxy_set_header Host $host;
        }
}
  • Add the following to the SSL definition above if SSL security should be hardened / improved:

            # protocol, session timout, server cipers
            # NOTE: ssl cache is handled by certbot
            # also see: https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf
    
            # restrict ciphers
            #
            # IMPORTANT: depending on your setup, it is possible that certbot will also define the ciphers used.
            # this can lead to a nginx error about already defined ciphers. in such a case, you can comment out
            # the cipher definition here.
            ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:!SHA1:!SHA256:!SHA384:!RC4:!aNULL:!eNULL:!Medium:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SEED";
    
            # use multiple curves  (only if dhparams file is used)
            ssl_ecdh_curve secp521r1:secp384r1;
    
            # reduce time to first byte
            ssl_buffer_size 4k;
    
            # add strict transport security
            add_header Strict-Transport-Security "max-age=15768000; must-revalidate; includeSubDomains; preload;" always;
  • Check the config and reload nginx:

    sudo nginx -s reload

If the server is accessible from the web, see the free SSL Labs page to check the sites SSL security.

Open a web browser, navigate to your Infinite Scale URL https://ocis.example.com and log in as admin user with the password returned by the ocis init command.

Apache as Reverse Proxy

Whenever a configuration change has been made, you need to do a configuration check and reload the Apache configuration. This can be done with two methods as described below. Select your preferred one. For ease of writing, the examples show sudo apache2ctl -k graceful.
  • sudo apache2ctl -k graceful

    Note that this command includes checking and reloading the config in the same step.

  • sudo apache2ctl -t
    sudo systemctl reload apache2

    Note that using systemctl reload apache2 alone will NOT validate your configuration but will execute the command in a clean environment and not in the current user environment.

Prepare Apache for certbot

To set up Apache as a reverse proxy with Let’s Encrypt TLS certificates, create a file called e.g. ocis under /etc/apache2/sites-available with the following content:

<IfModule mod_rewrite.c>
  <VirtualHost *:80>
    ServerName ocis.example.com
  </VirtualHost>
</IfModule>

Activate the new Apache config and reload Apache:

sudo ln -s /etc/apache2/sites-available/ocis /etc/apache2/sites-enabled/ocis
sudo apache2ctl -k graceful

Issuing a Certificate via certbot for Apache

Run certbot to issue the TLS certificates:

sudo certbot --apache -d ocis.example.com

Finalize the Apache Configuration

Adapt the config to redirect automatically to https, use the newly generated certificates and add the required proxy configuration. The full config should look like this:

<IfModule mod_rewrite.c>
  <VirtualHost *:80>
    ServerName ocis.example.com

    # redirect all http urls to https
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]

  </VirtualHost>
</IfModule>

<IfModule mod_ssl.c>
  <VirtualHost *:443>
    ServerName ocis.example.com

    SSLProxyEngine on
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off

    ProxyPass / http://localhost:9200/
    ProxyPassReverse / http://localhost:9200/

    #important, otherwise 400 errors from idp
    ProxyPreserveHost on

    ## Actual values to be added by certbot
    # SSLCertificateFile /etc/letsencrypt/live/ocis.example.com/fullchain.pem
    # SSLCertificateKeyFile /etc/letsencrypt/live/ocis.example.com/privkey.pem

    # Include /etc/letsencrypt/options-ssl-apache.conf
    # SSLOpenSSLConfCmd DHParameters /etc/letsencrypt/ssl-dhparams.pem
  </VirtualHost>
</IfModule>

Add the following to the SSL definition above if SSL security should be hardened / improved:

# restrict ciphers
SSLCipherSUite  "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:!SHA1:!SHA256:!SHA384:!RC4:!aNULL:!eNULL:!Medium:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SEED"

# use multiple curves (only if dhparams file is used)
SSLOpenSSLConfCmd Curves secp521r1:secp384r1

# add strict transport security
SSLOptions +StrictRequire
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

# disable ssl compression
SSLCompression off

Reload Apache:

sudo apache2ctl -k graceful

See the linked documentation how to enable the http2 protocol for Apache.

If the server is accessible from the web, see the free SSL Labs page to check the sites SSL security.

Open a web browser, navigate to your Infinite Scale URL https://ocis.example.com and log in as admin user with the password returned by the ocis init command.