Homepage    |    GitHub    |    API    |    Wiki    |    FAQ

Install Joplin Server without docker in Proxmox

Hello forum,

Here are the steps I took to install Joplin Server inside of an LXC container running in Proxmox. I used Debian 11 as the base image, checked the box for unprivileged container and nesting. I would be grateful if others could try this as well and let me know if you run into any issues.

  1. Install needed packages
apt install -y git vim curl postgresql-13 python2.7 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
  1. Generate https certs, be sure to enter the IP address of the server as the Common Name
openssl req -x509 -nodes -days 10000 -newkey rsa:4096 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
  1. Switch to postgres user to create database
su postgres
psql
CREATE DATABASE joplin;
CREATE USER joplin with password 'joplinrocks';
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO joplin;
  1. As root, create joplin directory and joplin user
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
  1. Copy needed files from git repo
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/
  1. Build application using npm
cd /opt/joplin/
npm config set python python2.7
npm install --ignore-scripts
npm run bootstrap
npm run bootstrapServerOnly
npm run build
npm install jquery
npm i @fortawesome/fontawesome-free
  1. Create autostart file for PM2 to use
joplin@joplin-server:~$ 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": "joplinrocks",
      "POSTGRES_USER": "joplin",
      "APP_BASE_URL": "https://<your ip>/joplin",
      "NODE_ENV": "development"
        }
      }
  ]
}

joplin@joplin-server:~$
  1. Add cron to joplin user to autostart server on boot
@reboot sh -c 'cd /opt/joplin/packages/server/ && pm2 start /opt/joplin/packages/server/ecosystem.config.js'
  1. Switch back to root user and enable proxy services in Apache
a2enmod proxy
a2enmod proxy_http
a2enmod ssl
  1. Create reverse proxy in Apache
root@joplin-server:~# cat /etc/apache2/sites-available/000-default-ssl.conf
<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 <your ip>
    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>
root@joplin-server:~#
  1. Enable site
a2ensite 000-default-ssl
  1. Reboot
3 Likes

Hi,
I tested your tutorial and I found one error at the moment I want to start the server:

[PM2][WARN] Applications joplin-server not running, starting...
[PM2][ERROR] Error: Script not found: /home/joplin/packages/server/dist/app.js

The error seems okay because we point to no folder. I corrected the path to this first, because in my folder structure I have joplin for the user and then anoter joplin folder for the git download:

/home/joplin/joplin/packages/server/dist/app.js

But error is the same. So I take a look and found out that there is no folder /dist/ in /packages/server/ and I also can't find a file app.js

Can you tell me the content of the file app.js or to which file I have to point for start up the server?

Greetings
Dominik

Maybe tsc compilation failed somewhere. Run npm run tsc from the root to check.

1 Like

Hi,
I think I found the problem. There is a wrong path in the tutorial, point "7. Create autostart file for PM2 to use"

you have to change this line:

script: "/home/joplin/packages/server/dist/app.js",

to

script: "/opt/joplin/packages/server/dist/app.js",

Now the server is up and running:

[PM2][Initialization] Environment variable HOME (Linux) or HOMEPATH (Windows) are not set!
[PM2][Initialization] Defaulting to /etc/.pm2
[PM2][WARN] Applications joplin-server not running, starting...
[PM2] App [joplin-server] launched (1 instances)

Good catch, I must have missed that when writing/updating this. It seems I am also unable to edit the original post, possibly because too much time has passed since writing it.

1 Like

Yes, you can only change posts within a certain amount of time.

I've updated your post with the correct path.

1 Like

Thanks for this tutorial anyway. It helped a lot.

Short question for updating the server:

Is it possible to update the git repository, copy all files again and run the npm stuff again to bring my server up to date?

Sorry guys, I have an other question. pm2 says the server is running but I can't connect. The pm2 log looks like this:

PM2              | App [joplin-server:0] exited with code [1] via signal [SIGINT]
PM2              | App [joplin-server:0] starting in -fork mode-
PM2              | App [joplin-server:0] online
0|joplin-server  | 2021-10-20 10:18:00: App: Starting server v2.5.2 (prod) on port 22300 and PID 10810...
0|joplin-server  | 2021-10-20 10:18:00: App: Running in Docker: false
0|joplin-server  | 2021-10-20 10:18:00: App: Public base URL: https://xxx.xx/joplin
0|joplin-server  | 2021-10-20 10:18:00: App: API base URL: https://xxx.xx/joplin
0|joplin-server  | 2021-10-20 10:18:00: App: User content base URL: xxx.xx/joplin
0|joplin-server  | 2021-10-20 10:18:00: App: Log dir: /opt/joplin/packages/server/logs
0|joplin-server  | 2021-10-20 10:18:00: App: DB Config: {
0|joplin-server  |   client: 'pg',
0|joplin-server  |   name: 'joplin',
0|joplin-server  |   slowQueryLogEnabled: false,
0|joplin-server  |   slowQueryLogMinDuration: 10000,
0|joplin-server  |   user: 'joplin',
0|joplin-server  |   password: '***',
0|joplin-server  |   port: 5432,
0|joplin-server  |   host: 'localhost'
0|joplin-server  | }
0|joplin-server  | 2021-10-20 10:18:00: App: Trying to connect to database...
0|joplin-server  | 2021-10-20 10:18:00: App: Connection check: {
0|joplin-server  |   latestMigration: { name: '20190913171451_create.js' },
0|joplin-server  |   isCreated: true,
0|joplin-server  |   error: null
0|joplin-server  | }
0|joplin-server  | [Error: EACCES: permission denied, unlink '/opt/joplin/packages/server/temp/joplin.sqlite'] {
0|joplin-server  |   errno: -13,
0|joplin-server  |   code: 'EACCES',
0|joplin-server  |   syscall: 'unlink',
0|joplin-server  |   path: '/opt/joplin/packages/server/temp/joplin.sqlite'
0|joplin-server  | }

The server is restarting all the time. What does this error Mean: EACCES: permission denied, unlink....?

I did the setup for postgresql, so why he want to connect to sqlite?

Seem like I miss something.

Thanks for your help...

This looks like a password issue between what you configured when setting up the user in Postgres and what is in the /opt/joplin/packages/server/ecosystem.config.js file. Try resetting the password you set for the joplin user in Postgres.

Sorry for this late reply. I first tried to fix/set the password for the postgres user to the same like in the ecosystem.config.js file. But this didn't work or I did something wrong.

So I decided to start from scratch today with a complete new Ubutnu 20.04 LTS (used it at the first approach, too).

At npm run bootstrap I get this error message: lerna ERR! npm install exited 1 in '@joplin/server'

I searched the net and tried some things I found there but I can't find the issue.

I think I haven't enough backround knowledge in building to do it and so stop at this point. Maybe I can do it later if I have some more knowledge about this things.

Thanks for your fast help anyway.

Greetings Dominik

Thank you for the guide. I am trying to get this to work but during step 6 (building application), when running npm run bootstrap, I get the following error:

npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@joplin%2fhtmlpack - Not found
npm ERR! 404
npm ERR! 404  '@joplin/htmlpack@~2.6' is not in this registry.

So it looks like the 2.6 version htmlpack is missing from the repo?
Searching for the error unfortunately did not yield any useful results. Any hints on how to proceed would be appreciated!

Hi, for solving 'joplin/htmlpack@~2.6' dependency problem you could copy additional package before bootstrap:
cp -r joplin/packages/htmlpack/ /opt/joplin/packages/