Nextcloud 13 in a Jail with php 7.2 and nginx

Installing Nextcloud 13 was trivial and it needs only few hours of concentration.

  1. create new jail for the Nextcloud installation
    • keep in mind that u use very short jail names in fact of the hack 88 problem
  2. extends u’re pf.conf firewall settings
    1. jail can communicate with the world
    2. use a custom port like 10443 to forward incomming traffic to the Nextcloud jail
  3. create database and user for Nextcloud instance
  4. extract ports in jail
  5. install nginx
  6. install php72
  7. install nextcloud
  8. change config files
  9. initialize Nextcloud

Sounds easy, it is easy, isn’t it.

I’ll give u some helpful code snippets to the key facts.

iocage create -r 11.1-RELEASE -n cloud-nc ip4_addr="re0|10.0.0.10/24" boot=on vnet=off notes="nextcloud"
iocage console cloud-nc

creates a jail and log into

  • Now install nginx, php72 and Nextcloud from the ports
  • logout from the jail and create follow fstab entry
iocage fstab -l cloud-nc
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| INDEX |                                                                               FSTAB ENTRY                                                                                      |
+=======+================================================================================================================================================================================+
| 0     | /iocage/jails/cloud-nc/root/usr/local/www/nextcloud /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nextcloud nullfs ro 0 0                                    |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1     | /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nc-data /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nextcloud/data nullfs rw,union 0 0     |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2     | /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nc-config /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nextcloud/config nullfs rw,union 0 0 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 3     | /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nc-apps /iocage/jails/cloud-nc/root/usr/local/www/www.somenicedomain.de/nextcloud/apps nullfs rw,union 0 0     |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

This is important! U have NOT to copy the Nextcloud files. We’ll mount the files from the ports as ro with nullfs. Nextcloud needs write right to the data, config and apps directory. It will merge the standard content and the custom content. Keep in mind, if there is the same directory in nc-data and data, the directory inside nc-data will overwrite all of the standard. Do not mount a directory to the root of the Nextcloud directory with nullfs and union.

Customize the php configuration

diff php.ini php.ini-production 
383c383
< max_execution_time = 180
---
> max_execution_time = 30
672c672
< post_max_size = 50M
---
> post_max_size = 8M
825c825
< upload_max_filesize = 50M
---
> upload_max_filesize = 2M
939c939
< date.timezone = Europe/Berlin
---
> ;date.timezone =
1351c1351
< session.save_path = "/tmp"
---
> ;session.save_path = "/tmp"
diff php-fpm.d/www.conf php-fpm.d/www.conf.default 
388,392c388,392
< env[HOSTNAME] = $HOSTNAME
< env[PATH] = /usr/local/bin:/usr/bin:/bin
< env[TMP] = /tmp
< env[TMPDIR] = /tmp
< env[TEMP] = /tmp
---
> ;env[HOSTNAME] = $HOSTNAME
> ;env[PATH] = /usr/local/bin:/usr/bin:/bin
> ;env[TMP] = /tmp
> ;env[TMPDIR] = /tmp
> ;env[TEMP] = /tmp

 

Customize the nginx configuration

upstream php-handler {
    server 10.1.1.10:9000;
}

server {
    ### domain names
    server_name    www.somenicedomain.de somenicedomain;
    listen         10443 ssl;

    ### ssl
    ssl_certificate     /usr/local/etc/ssl/certs/www.somenicedomain.de.chained.crt;
    ssl_certificate_key /usr/local/etc/ssl/certs/www.somenicedomain.de.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;


    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000;
    # includeSubDomains; preload;";
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;


    ### root / log files
    root          /usr/local/www/www.somenicedomain.de/nextcloud;
    access_log    /usr/local/www/www.somenicedomain.de/log/access.log main;
    error_log     /usr/local/www/www.somenicedomain.de/log/error.log warn;

    index    index.html index.htm index.php;

    # don't log robots/favicon 404 errors
    location ~ ^/(robots\.txt|favicon\.ico) {
        log_not_found    off;
    }

    # no access to . files
    #location ~/\. {
    #    deny    all;
    #}
 
 
    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }


    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;



    location / {
        rewrite ^ /index.php$uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff|svg|gif)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don't log access to assets
        #access_log off;
        access_log    /usr/local/www/www.somenicedomain.de/log/access_static.log main;
        expires       30d;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        #access_log off;
        access_log    /usr/local/www/www.somenicedomain.de/log/access_static.log main;
        expires       30d;
    }
}

 

Restart nginx and u’re firewall. Open a browser and start the setup of Nextcloud.

GoAccess.io access log file analyzer / How search engines forget but not the spammer

It’s years ago that I maintained the http://www.java-club.de site, many years ago. Unused potential, sure.

Server is running, I’m the only maintainer and administrator. Nobody else configure all the whole services hence I had and I have to dive deeply into the man pages and tutorials. Probably Postfix, Dovecot and RSPAMD was the hardest configuration tasks. It runs very smoothly.

Now I would like to analyze my web access log files. After all the long time, It’s interesting how many unique visitors read all the stuff. First, it’s interesting how the search engines can forget a website. It’s long time ago there was a lot of page impressions and visitors. Now, I can say search engines forget very well. Badly the spammer not. RSPAMD and all the other security stuff works so well. Thanks.

Back to the topic. Here is the link to the website https://goaccess.io.

root@www-wp:~ # whereis goaccess
goaccess: /usr/ports/sysutils/goaccess
root@www-wp:~ # cd /usr/ports/sysutils/goaccess
root@www-wp:/usr/ports/sysutils/goaccess # make install clean

Go to the directory with the access file and call

root@www-wp:/somedirectory/www/someNiceDomain.de/log # goaccess access.log --log-format=COMBINED

The console output its really nice and helpful. It needs only one runtime library dependency. https://www.freshports.org/sysutils/goaccess/

FreeBSD and the Hack88 – 88 characters for mount points

A good way to increase the security of a server is to separate the services, program and libraries in a own container. Today, the most would say “Docker, Docker, Docker”. Yeah, it’s a valid solution. U can use docker, virtualization like https://opennebula.org or the FreeBSD specific http://www.bhyve.org. FreeBSD offers simple way for that since nearly 20 years, JAILS. Please take a look to the wikipedia link https://en.wikipedia.org/wiki/FreeBSD_jail.

Okay, back to the origin topic. 88 characters for mount points and what it’s the relation to jails? I use http://iocage.readthedocs.io/en/latest/ for managing jails in my FreeBSD 11.1 system. U’ll get a directory structure like

/iocage/jails/shortnameOfJail/root/usr/home/myUser/www/blog.somenicedomain.com/html

Congratulation u have a directory with 83 characters, but what’s the problem?

  1. Let’s install in a new jail wordpress, separate this php code from the rest of the system.
  2. Install wordpress from the ports collection.
  3. DON’T copy the /usr/local/www/wordpress directory!
  4. Instead USE nullfs and union with nullfs to mount the wordpress files

U’re fstab for the jail looks like

/usr/home/someUser/www/blog.someNiceDomain.de /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de nullfs rw 0 0

/iocage/jails/www-wp/root/usr/local/www/wordpress /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de/wp nullfs ro 0 0

/usr/home/someUser/www/blog.someNiceDomain.de/wp-root /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de/wp nullfs rw,union 0 0

/usr/home/someUser/www/blog.someNiceDomain.de/wp-content/plugins /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de/wp/wp-content/plugins nullfs rw,union 0 0

/usr/home/someUser/www/blog.someNiceDomain.de/wp-content/uploads /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de/wp/wp-content/uploads nullfs rw,union 0 0

/usr/home/someUser/www/blog.someNiceDomain.de/wp-content/themes /iocage/jails/www-wp/root/usr/local/www/blog.someNiceDomain.de/wp/wp-content/themes nullfs rw,union 0 0

Mount points with more than 88 character will cause an error. Really strange. Beliefe me in a jail environment it’s really easy to get mount points with more than 88 character. It’s like tetris that fits all in the existing 88 restriction. This behavior persists since FreeBSD 5 and will be solved around 16 years later in FreeBSD 12. Can anyone explain me why 88 characters? I live in a 2 high n world. 01011101 😉

Some useful links

http://iocage.readthedocs.io/en/latest/known-issues.html#character-mount-path-limitation

https://www.freebsd.org/cgi/man.cgi?query=statfs&sektion=2&manpath=freebsd-release-ports

statfs(2)

#define MFSNAMELEN	16	/*	length of type name including null */
#define MNAMELEN	88	/*	size of	on/from	name bufs */
#define STATFS_VERSION 0x20030518	/*	current	version	number */

struct statfs {
  ...
  char f_charspare[80]; /* spare string space */
  char f_fstypename[MFSNAMELEN]; /* filesystem type name */
  char f_mntfromname[MNAMELEN]; /* mounted filesystem */
  char f_mntonname[MNAMELEN]; /* directory on which mounted */
}

Es war einmal … ! – Re-Launch Java-Club.de

Es war einmal …

Während meines Studiums kam ich in meinem Praxissemster in Darmstadt mit der Programmiersprache Java in Berührung. Programmiert habe ich dort Tag und Nacht C / C++ und meine Guten Morgen, Mahlzeit und Guten Nacht Lektüre bildeten die Bücher von Scott Meyers und Bjarne Stroustrup. In der Firma gab es ein Team welches ein erstes Projekt in Java implementiert hat. Angetan von der Sprache fing ich 1999 an in Java zu implementieren und gründete den Java-Club.de in Merseburg. Es gab das ein oder andere Treffen, eine Art kleine JUG und das vor knapp 20 Jahren. Hoffentlich finde ich noch das ein oder andere Foto, unvorstellbar dass Fotos damals nicht mal eben so mit dem Handy aufgenommen wurden. Ich glaube damals hatte ich einen Nokia 6210. 🙂

Was ist jetzt zu erwarten?

Ein neues Forum? Eine Art JUG? .. Nein!

Es gibt jede Menge Artikel, Informationen und Sammlungen die sich lokal auf meiner Platte oder im Github im Markdown Format befinden. Ganz frisch ist noch das Aufsetzen meines eigenen Servers. Damit beginne ich und werde eine Art Tutorial bieten für das Aufsetzen, Grundlagen in der Administration, Security Konzepte, Benutzer Konzepte über den Betrieb und Konfiguration von Postfix, Dovecot und RSPAMD sowie Unbound als DNS Server bieten.

Vielleicht ist für den ein oder anderen etwas nützliches dabei. Soweit es meine Zeit und Muse hergibt verfasse ich die Texte auf Englisch.