jason schaefer . com

"arguing that you don’t care about the right to privacy because you have nothing to hide is no different than saying you don’t care about free speech because you have nothing to say."

Tag: nextcloud

  • Installing Nextcloud v31 on Debian 13 (trixie) using php8.4-fpm, redis and apcu

    This is a concise tutorial, it is not meant to be a hand holding step by step guide. Please comment or contact me if you find errors.

    Prerequisites:
    Setup a domain/sub domain with an A record to the ip of the server or a CNAME to a “dynamic DNS” hostname. I recommend https://freedns.afraid.org.
    The server needs to have ports 80 and 443 reachable to the public. The DNS must be propagated for letsencrypt to be successful.

    Start the install

    apt-get install apache2 mariadb-server libapache2-mod-fcgid php-fpm php php-gd php-json php-mysql php-curl php-mbstring php-intl php-imagick php-xml php-zip php-bz2 python3-certbot-apache php-apcu redis-server php-redis php-bcmath php-gmp ffmpeg curl coreutils libmagickcore-7.q16-10-extra

    Download Nextcloud

    wget https://download.nextcloud.com/server/releases/latest-31.tar.bz2

    Make sure the md5 matches

    md5sum latest-31.tar.bz2
    curl https://download.nextcloud.com/server/releases/latest-31.tar.bz2.md5

    Extract the tar file and change permissions

    tar xfv latest-31.tar.bz2
    mv nextcloud/ /var/www/example.com/
    chown www-data:www-data -R /var/www/example.com/

    [Setup Apache]

    Create a apache virtual site

    cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf

    edit /etc/apache2/sites-available/example.com.conf

    uncomment and change

    ServerName example.com

    change the document root

    DocumentRoot /var/www/example.com

    change log location if you would like

    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined

    enable example.com in apache

    a2ensite example.com

    a2enmod proxy_fcgi setenvif rewrite headers env dir mime userdir dav ssl
    a2enconf php8.4-fpm
    service apache2 restart

    Setup Letsencrypt

    certbot --apache -d example.com

    tell it to redirect http to https

    Edit /etc/apache2/sites-enabled/example.com-le-ssl.conf

      <Directory /var/www/example.com/>
        Require all granted
        AllowOverride All
        Options FollowSymLinks MultiViews
    
        <IfModule mod_dav.c>
          Dav off
        </IfModule>
      </Directory>

    To avoid certain race conditions between the /etc/apache2/sites-available/example.com.conf and /etc/apache2/sites-available/000-default.conf
    I prefer to remove example.com.conf and move the http->https redirect into the 000-default.conf

    cat /etc/apache2/sites-available/example.com.conf

    ….snip…


    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with “a2disconf”.
    #Include conf-available/serve-cgi-bin.conf
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>

    # vim: syntax=apache ts=4 sw=4 sts=4 sr noet

    copy the rewrite rule at the bottom:

    RewriteEngine on 
    RewriteCond %{SERVER_NAME} =example.com 
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] 

    edit and paste into the default conf

    vi /etc/apache2/sites-enabled/000-default.conf

    This is what 000-default.conf should look like

    <VirtualHost *:80>

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

    </VirtualHost>

    [Configure PHP]

    edit /etc/php/8.4/fpm/php.ini
    memory_limit = 768M
    upload_max_filesize = 1024M
    post_max_size = 1024M
    max_execution_time = 300

    [Create a database, user and password for nextcloud]

    mariadb -uroot
    
    CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'PASSWORD';
    CREATE DATABASE IF NOT EXISTS nextcloud;
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES ON nextcloud.* TO 'nextcloud'@'localhost';
    FLUSH privileges;

    [Install Nextcloud]

    run the installer at https://example.com/

    [Setup Redis]

    edit /etc/redis/redis.conf
    Under the # Unix socket. section add the following

    port 0
    unixsocket /run/redis/redis-server.sock
    unixsocketperm 770

    add www-data to redis group

    usermod -a -G redis www-data


    /etc/group will now have an entry like this “redis:x:119:www-data”

    systemctl enable redis-server

    Add the following to /var/www/example.com/config/config.php

    This is using APCu for memcache and Redis for distributed caching and file locking. Here we use a socket to connect to redis-server.

      'memcache.local' => '\OC\Memcache\APCu',
    
      'memcache.distributed' => '\OC\Memcache\Redis',
      'memcache.locking' => '\OC\Memcache\Redis',
    
      'redis' => [
        'host'     => '/run/redis/redis-server.sock',
        'port'     => 0,
      ],

    add the following to /etc/php/8.4/fpm/php.ini

    opcache.enable=1
    opcache.enable_cli=1
    opcache.memory_consumption=200
    opcache.interned_strings_buffer=16
    opcache.max_accelerated_files=10000
    opcache.save_comments=1
    opcache.revalidate_freq = 1
    systemctl restart redis-server
    
    systemctl restart apache2

    add apc cli enabling line in here -> /etc/php/8.4/cli/php.ini

    apc.enable_cli=1
    systemctl restart php8.4-fpm.service


    [Setup cron for Nextcloud]

    crontab -u www-data -e
    */5 * * * * php -f /var/www/example.com/cron.php

    done;

  • Install coturn for nextcloud STUN and TURN services

    The nightmare that is NAT: Network Address Translation. We require TURN: Traversal Using Relays around NAT and STUN: Session Traversal Utilities for NAT. These servers facilitate the connections between clients, navigating around NAT, for voice and video communications*. In this implementation we assume the coturn server will be publicly routeable (have a public ip).

    install coturn

    apt-get install coturn

    enable it

    vi /etc/default/coturn
    TURNSERVER_ENABLED=1

    Fixup the turnserver config. I recommend using “/” to search through your config and uncomment the following items, this keeps your original config as close to stock as possible. It does have the downside of being a pain to read, see my grep trick below to help with that.

    vi /etc/turnserver.conf
    
    fingerprint
    use-auth-secret
    static-auth-secret=[some long password]
    realm=example.com
    total-quota=100
    stale-nonce
    cert=/etc/letsencrypt/live/example.com/cert.pem
    pkey=/etc/letsencrypt/live/example.com/privkey.pem
    syslog
    no-multicast-peers
    no-cli
    no-rfc5780
    no-stun-backward-compatibility
    response-origin-only-with-rfc5780

    Here is a description of each parameter at coturns github

    grep out all the comments and whitespace so you can see what is enabled and confirm your config is correct

    grep -v ^# /etc/turnserver.conf |grep .

    Use letsencrypt with turnserver

    We will use the same certs as we are using for Nextcloud. See my post on installing Nextcloud server.
    The letsencrypt directory needs to be opened up for coturn to use it. The best way to do this is add turnserver to the group ssl-cert and then allow this group access to the certs. First fixup the group

    usermod -a -G ssl-cert turnserver

    Keep the owner as root and change the group to ssl-cert. Then change the group to have read and execute permissions.

    chown root:ssl-cert /etc/letsencrypt/live/ /etc/letsencrypt/archive/
    
    chmod g+rx /etc/letsencrypt/archive/ /etc/letsencrypt/live/

    Additionally, the private key is only read and writeable by root as shown below.

    #confirm perms are not ok
    ls -l /etc/letsencrypt/archive/example.com/privkey1.pem
    -rw------- 1 root root  241 Nov 22 17:49 privkey1.pem
    
    

    Change owner (chown) and change mode (chmod) for the privkey1.pem. Future renewed keys will continue with these set permissions. So privkey2.pem will also have “-rw-r—– root ssl-cert”.

    chown root:ssl-cert /etc/letsencrypt/archive/example.com/privkey1.pem
    
    chmod g+r /etc/letsencrypt/archive/example.com/privkey1.pem
    
    #confirm perms are good
    ls -l /etc/letsencrypt/archive/example.com/privkey1.pem
    -rw-r----- 1 root ssl-cert 241 Nov 22 17:49 privkey1.pem

    Verify and test. Look through the log for coturn after a restart. Press “G” to go to the end of log and then scroll back up to see any errors from your last restart.

    systemctl restart coturn
    journalctl -u coturn

    run the turnutils client against the server. This package is part of coturn
    First test turn://

    turnutils_uclient -p 3478 -W [static-auth-secret] -v -y example.com

    and then turns:// (-S)

    turnutils_uclient -p 3478 -W [static-auth-secret] -v -y example.com -S

    The end of this connection should look like this:

    8: : Total transmit time is 4
    8: : Total lost packets 0 (0.000000%), total send dropped 0 (0.000000%)
    8: : Average round trip delay 93.400000 ms; min = 88 ms, max = 104 ms
    8: : Average jitter 3.700000 ms; min = 0 ms, max = 13 ms

    Now we add this server to Nextcloud, under Administration Settings -> Talk
    set STUN to “example.com:port”
    set to TURN to “turn: and turns:” | “example.com” | “[static-auth-secret]” | “UDP and TCP”

    Look for the green check mark to see that it works

    * Here is a description of how TURN and STUN work from Nextclouds documentation

    Talk tries to establish a direct peer-to-peer (P2P) connection, thus on connections beyond the local network (behind a NAT or router), clients do not only need to know each others public IP, but the participants local IPs as well. Processing this, is the job of a STUN server. As there is one preconfigured for Nextcloud Talk that is operated by Nextcloud GmbH, for this case nothing else needs to be done.
    
    But in many cases, especially in combination with firewalls or symmetric NAT, a direct P2P connection is not possible, even with the help of a STUN server. For this a so called TURN server needs to be configured additionally.
    
    Nextcloud Talk will try direct P2P in the first place, use STUN if needed and TURN as last resort fallback. Thus to be most flexible and guarantee functionality of your Nextcloud Talk instance in all possible connection cases, you would want to setup a TURN server.
  • Installing Nextcloud v22 on Debian v11 (buster) using Redis

    This is a concise tutorial, it is not meant to be a hand holding step by step guide. Please comment or contact me if you find errors.

    Prerequisites:
    Setup a domain/sub domain with an A record to the ip of the server or a CNAME to a “dynamic DNS” hostname. I recommend https://freedns.afraid.org.
    The server needs to have ports 80 and 443 reachable to the public. The DNS must be propagated for letsencrypt to be successful.

    Start the install

    apt-get install apache2 mariadb-server libapache2-mod-php php-gd php-json php-mysql php-curl php-mbstring php-intl php-imagick php-xml php-zip php-bz2 python3-certbot-apache redis-server php-redis php-bcmath php-gmp ffmpeg curl coreutils libmagickcore-6.q16-6-extra

    Download Nextcloud

    wget https://download.nextcloud.com/server/releases/latest-22.tar.bz2

    Make sure the md5 matches
    md5sum latest-22.tar.bz2
    curl https://download.nextcloud.com/server/releases/latest-22.tar.bz2.md5

    Extract the tar file and change permissions
    tar xfv nextcloud-22.x.tar.bz2
    mv nextcloud/ /var/www/example.com/
    chown www-data:www-data -R /var/www/example.com/

    Setup Apache

    Create a apache virtual site
    cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf

    edit /etc/apache2/sites-available/example.com.conf
    uncomment and change
    ServerName example.com

    change the document root
    DocumentRoot /var/www/example.com

    change log location if you would like
    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined

    a2ensite example.com

    a2enmod php7.4 rewrite headers env dir mime userdir dav ssl

    service apache2 restart

    Setup Letsencrypt

    certbot --apache -d example.com

    tell it to redirect http to https

    Edit /etc/apache2/sites-enabled/example.com-le-ssl.conf

      <Directory /var/www/example.com/>
        Require all granted
        AllowOverride All
        Options FollowSymLinks MultiViews
        <IfModule mod_dav.c>
          Dav off
        </IfModule>
      </Directory>
    

    To avoid certain race conditions between the /etc/apache2/sites-available/example.com.conf and /etc/apache2/sites-available/000-default.conf
    I prefer to remove example.com.conf and move the http->https redirect into the 000-default.conf

    cat /etc/apache2/sites-available/example.com.conf

    ….snip…
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with “a2disconf”.
    #Include conf-available/serve-cgi-bin.conf
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>

    # vim: syntax=apache ts=4 sw=4 sts=4 sr noet

    copy the rewrite rule at the bottom:

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    
    edit and paste into the default conf
    vi /etc/apache2/sites-enabled/000-default.conf
    

    <VirtualHost *:80>

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

    </VirtualHost>

    Configure php
    edit /etc/php/7.4/apache2/php.ini

    memory_limit = 768M
    upload_max_filesize = 1024M
    post_max_size = 1024M
    max_execution_time = 300

    Create a database, user and password for nextcloud

    mariadb -uroot

    CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'PASSWORD';
    CREATE DATABASE IF NOT EXISTS nextcloud;
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES ON nextcloud.* TO 'nextcloud'@'localhost';
    FLUSH privileges;

    run the installer at https://example.com/

    Now we can setup Redis

    edit /etc/redis/redis.conf
    Under the # Unix socket. section add the following

    port 0
    unixsocket /var/run/redis/redis-server.sock
    unixsocketperm 770
    

    add www-data to redis group

    usermod -a -G redis www-data
    /etc/group will now have an entry like this “redis:x:119:www-data”

    systemctl enable redis-server

    Add the following to /var/www/example.com/config/config.php

    'memcache.local' => '\\OC\\Memcache\\Redis',
      'memcache.distributed' => '\\OC\\Memcache\\Redis',
      'memcache.locking' => '\\OC\\Memcache\\Redis',
      'redis' =>
      array (
        'host' => '/var/run/redis/redis-server.sock',
        'port' => 0,
        'dbindex' => 0,
        'timeout' => 1.5,
      ),
    

    edit /etc/php/7.4/apache2/php.ini

      opcache.enable=1
      opcache.enable_cli=1
      opcache.memory_consumption=128
      opcache.interned_strings_buffer=8
      opcache.max_accelerated_files=10000
      opcache.save_comments=1
      opcache.revalidate_freq = 1
    

    systemctl restart redis-server
    systemctl restart apache2
    Setup cron for Nextcloud

    crontab -u www-data -e
    */5 * * * * php -f /var/www/example.com/cron.php

    done;