Post

Joplin Server 2.9 LXC Build

Joplin is my current note-taking app of choice because markdown notes are easy to read and I like the cross-platform support. Markdown is supported by many applications so there is no threat of being locked into a specific application.

In order to centrally store and share notes with other users in my home network, I reverse-engineered the docker build file and ran Joplin server in an Debian based LXC. I have included all of the steps to build your own.

  1. Start by ensuring the apt tree is up-to-date. Apache2 is needed for reverse proxy functionality, however nginx can be used in its place.
    1
    2
    3
    4
    5
    6
    7
    8
    
     apt update
     apt upgrade
     apt install -y git vim curl postgresql make gcc g++ apache2
     curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
     apt update
     apt upgrade
     apt install nodejs
     npm install -g pm2
    
  2. Generate a self-signed https certificate, be sure to enter the IP address of the server as the Common Name. You can also use Lets Encrpyt if you so choose.
    1
    
     openssl req -x509 -nodes -days 10000 -newkey rsa:4096 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
    
  3. Switch to the postgres user to create a database and user for Joplin to use. Generate a secure password to use here. One method of doing so is using openssl
    1
    2
    3
    
     openssl rand -base64 32
     su postgres
     psql
    
    1
    2
    3
    4
    
     REVOKE ALL PRIVILEGES ON SCHEMA public FROM PUBLIC;
     CREATE DATABASE joplin;
     CREATE USER joplin with password 'supers$cret';
     GRANT ALL PRIVILEGES ON DATABASE joplin to joplin;
    
  4. As root, create joplin directory and joplin user
    1
    2
    3
    4
    5
    
     mkdir -p /opt/joplin/packages/{fork-sax,lib}
     useradd --create-home --shell /bin/bash joplin
     chown -R joplin:joplin /opt/joplin
     su -l joplin
     git clone https://github.com/laurent22/joplin.git
    
  5. Copy needed files from git repo into the joplin directory
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     cp joplin/packages/fork-sax/package*.json /opt/joplin/packages/fork-sax/
     cp joplin/packages/lib/package*.json /opt/joplin/packages/lib/
     cp joplin/lerna.json /opt/joplin/
     cp joplin/tsconfig.json /opt/joplin/
     cp joplin/package*.json /opt/joplin/
     cp -r joplin/packages/fork-htmlparser2/ /opt/joplin/packages/
     cp -r joplin/packages/turndown-plugin-gfm/ /opt/joplin/packages
     cp -r joplin/packages/turndown/ /opt/joplin/packages/
     cp -r joplin/packages/renderer/ /opt/joplin/packages/
     cp -r joplin/packages/server/ /opt/joplin/packages/
     cp -r joplin/packages/tools/ /opt/joplin/packages/
     cp -r joplin/packages/lib /opt/joplin/packages/
     cp -r joplin/packages/htmlpack/ /opt/joplin/packages/
    
  6. Build the application using npm
    1
    2
    
     cd /opt/joplin/
     BUILD_SEQUENCIAL=1 yarn install --inline-builds
    
  7. Create autostart file for PM2 to use, updating the server IP. This will set the necessary environment variables for Joplin to use.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
     $ cat /opt/joplin/packages/server/ecosystem.config.js
     module.exports = {
     apps : [
         {
             name: "joplin-server",
             script: "/opt/joplin/packages/server/dist/app.js",
             watch: false,
             env: {
             "DB_CLIENT": "pg",
         "POSTGRES_DATABASE": "joplin",
         "POSTGRES_PASSWORD": "supers$cret",
         "POSTGRES_USER": "joplin",
         "APP_BASE_URL": "https://<server IP>/joplin",
         "NODE_ENV": "development"
             }
         }
     ]
     }
    
  8. Add the following line as a cron to joplin user to autostart server on boot
    1
    
     @reboot sh -c 'cd /opt/joplin/packages/server/ && pm2 start /opt/joplin/packages/server/ecosystem.config.js'
    
  9. Switch back to root user and enable proxy services in Apache
    1
    2
    3
    
     a2enmod proxy
     a2enmod proxy_http
     a2enmod ssl
    
  10. Create reverse proxy in Apache using the configuration below, updating the server IP.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    <IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        ProxyPreserveHost On
        ProxyPass "/joplin" http://localhost:22300
        ProxyPassReverse "/joplin" http://localhost:22300
    
        ServerName <serverIP/hostname>
        SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
        SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
    
        SSLEngine on
    
        # Intermediate configuration, tweak to your needs
        SSLProtocol             all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        SSLHonorCipherOrder     off
        SSLSessionTickets       off
    
        SSLOptions +StrictRequire
    
        # Add vhost name to log entries:
        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
        LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
    </VirtualHost>
    </IfModule>
    
  11. Enable the site with a2ensite.
    1
    
    a2ensite 000-default-ssl
    
  12. Reboot the server to ensure services will auto-start on their own. Running the command pm2 logs as the joplin user can be used to diagnose any issues.

With the server running, connect to the UI in a web browser at https://<serverIP>. The default user is admin@localhost and the default password is admin. You should change this after logging in successfully. From here, create new users and then set the username, password, and server URL within the Joplin desktop application. If you do not have a signed certificate, check the box to Ignore TLS certificate errors under the Advanced Sync Settings.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.

© Kris Crawford. Some rights reserved.

Using the Chirpy theme for Jekyll.