The way to an own clowd - Part 7
The way to an own clowd (part 7) - The First Service: Joplin
Notes, to-do lists, ideas, and projects: Our digital everyday life demands a reliable and flexible solution for organizing information.
Joplin is an open-source alternative to Evernote and similar tools, allowing users to keep complete control over their data. What makes it special: Joplin can be fully self-hosted – including synchronization across all devices, Markdown support, and robust encryption options.
This time I show how to install an own backend and the official apps.
For this you should already finished the following tutorials:
- Part 1: The own server
- Part 2: The right database
- Part 3: Connecting to the outside
- Part 4: The own shipping yard
- Part 5: DIY Secure Backups
- Part 6: Frameworks for the cloud environment
Preparations
First, make sure you are logged in as root:
su
Then open the psql
tool as the PostgreSQL administrator:
sudo -u postgres psql
In the psql
prompt, create a new user joplinuser
and the database joplin
:
CREATE USER joplinuser WITH PASSWORD '<A-STRONG-PASSWORD>';
CREATE DATABASE joplin WITH OWNER joplinuser;
GRANT ALL PRIVILEGES ON DATABASE joplin TO joplinuser;
Exit the tool afterwards.
For additional security, it is recommended to generate a random port for the Joplin backend:
echo $(shuf -i 1024-65535 -n 1)
This command will output a random number between 1024 and 65535.
Backend Setup
First, create the main directory for Joplin:
mkdir -p /opt/joplin
Next, create a file named docker-compose.yaml
in the /opt/joplin
directory with the following content:
services:
joplin-server:
image: localhost:5000/joplin/server:latest
container_name: joplin-server
environment:
- APP_BASE_URL=https://<CLOUD-DOMAIN> # Use your domain as configured in nginx
- DB_CLIENT=pg
- POSTGRES_PASSWORD=<STRONG_DATABASE_PASSWORD>
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplinuser
- POSTGRES_PORT=<POSTGRES_PORT>
- POSTGRES_HOST=host.docker.internal
ports:
- "22300:22300"
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
Because a local Docker registry is used, you can create and push a local copy of the official Joplin image:
docker pull joplin/server:latest
docker tag joplin/server:latest localhost:5000/joplin/server:latest
docker push localhost:5000/joplin/server:latest
To make the service accessible from outside, create a file called /etc/nginx/sites-available/joplin
with the following content (make sure to adjust the values!):
server {
listen <RANDOM_PORT_FROM_ABOVE> ssl;
server_name <CLOUD-DOMAIN>;
ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;
# Adjust maximum upload size if needed
client_max_body_size 512M;
location / {
proxy_pass http://localhost:22300;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
To activate the configuration in NGINX, create a symbolic link in /etc/nginx/sites-enabled
:
sudo ln -s /etc/nginx/sites-available/joplin /etc/nginx/sites-enabled/
Then restart the service:
sudo systemctl restart nginx
To automatically start Joplin on boot, you need a service configuration saved as /etc/systemd/system/joplin.service
:
[Unit]
Description=Joplin Server (Docker Compose)
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/joplin
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
Finally, run these commands to set up Joplin as a background service:
sudo systemctl daemon-reload
sudo systemctl enable joplin
sudo systemctl start joplin
The service is available when you can access https://<CLOUD-DOMAIN>:<JOPLIN-PORT>
in your browser and see the login screen.
The default username is usually admin@localhost
with the password admin
. It is strongly recommended to change the password immediately after your first login!
Setting up the Apps
Joplin provides dedicated apps for mobile devices and Mac: https://joplinapp.org/download/
To connect your device:
- Open the Joplin app on your device and go to Settings → Synchronization
- Select Joplin Server as the target
- Enter the following URL:
https://<CLOUD-DOMAIN>:<JOPLIN-PORT>
(e.g.https://cloud.my-name.eu:22300
) - Enter your Joplin server username and password
- Start synchronization
Conclusion
With Joplin, you can set up a powerful, secure, and flexible note-taking solution on your own server.
Setup with Docker is quick, operation is reliable, and with the matching apps for every device, your notes are always in sync and under your control.
Quick & Dirty
# your cloud domain and Postgres passwort
CLOUD_DOMAIN=cloud.example.com
STRONG_PASSWORD='CHOOSE_A_STRONG_PASSWORD'
# create Joplin Postgres user & database
sudo -u postgres psql <<EOF
CREATE USER joplinuser WITH PASSWORD '$STRONG_PASSWORD';
CREATE DATABASE joplin WITH OWNER joplinuser;
GRANT ALL PRIVILEGES ON DATABASE joplin TO joplinuser;
\\q
EOF
# 2. setup Joplin directory and docker-compose.yaml
sudo mkdir -p /opt/joplin
sudo tee /opt/joplin/docker-compose.yaml >/dev/null <<EOC
services:
joplin-server:
image: joplin/server:latest
container_name: joplin-server
environment:
- APP_BASE_URL=https://$CLOUD_DOMAIN
- DB_CLIENT=pg
- POSTGRES_PASSWORD=$STRONG_PASSWORD
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplinuser
- POSTGRES_PORT=5432
- POSTGRES_HOST=host.docker.internal
ports:
- "22300:22300"
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
EOC
# setup NGINX reverse proxy
sudo tee /etc/nginx/sites-available/joplin >/dev/null <<EONG
server {
listen 443 ssl;
server_name $CLOUD_DOMAIN;
ssl_certificate /etc/letsencrypt/live/$CLOUD_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$CLOUD_DOMAIN/privkey.pem;
client_max_body_size 512M;
location / {
proxy_pass http://localhost:22300;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EONG
sudo ln -sf /etc/nginx/sites-available/joplin /etc/nginx/sites-enabled/joplin
sudo systemctl reload nginx
# setup systemd service
sudo tee /etc/systemd/system/joplin.service >/dev/null <<EOSD
[Unit]
Description=Joplin Server (Docker Compose)
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/joplin
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
EOSD
# enable and start joplin service
sudo systemctl daemon-reload
sudo systemctl enable joplin
sudo systemctl start joplin