Skip to content

Run Yor Own Server

To run Jvln Server, you will need:

  • A server (usually a VPS), with the ability to expose TCP and UDP ports to the internet.
  • A registered domain name and the ability to manage it’s DNS

Jvln Server supports TLS over TCP and uses SNI (Server Name Indication) to resolve which tunnel that the client request should be directed.

To set this up, a wildcard certificate from a trusted CA (Certificate Authority) is required. The easiest way to get a certificate is via the ACME protocol.

The recommended tool for this is goacme/lego. You can configure lego with over 200 DNS providers to automatically provision wildcard certificates.

You can run the following command to install the latest version of the lego binary on your machine.

Terminal window
curl -sL https://api.github.com/repos/go-acme/lego/releases/latest \
| grep '"tag_name"' \
| sed 's/.*"v\([^"]*\)".*/\1/' \
| xargs -I{} sh -c \
'ARCH=$(uname -m | sed "s/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/armv7/"); \
echo "\nInstalling lego_v{}_linux_${ARCH}..."; \
curl -sL "https://github.com/go-acme/lego/releases/download/v{}/lego_v{}_linux_${ARCH}.tar.gz" \
| tar -xz -C /usr/local/bin lego && \
echo "Successfully installed lego to /usr/local/bin/lego.\n"'
Terminal window
DOMAIN="example.org"
DESEC_TOKEN="<YOUR-DESEC-API-KEY>" \
/usr/local/bin/lego run \
--accept-tos \
--path /var/lib/lego \
--dns desec \
--dns.propagation.wait 120s \
-d "*.${DOMAIN}" \
-d "${DOMAIN}" \
--server letsencrypt

This will generate certificate files at the following paths:

  • /var/lib/lego/certificates/_.example.org.crt
  • /var/lib/lego/certificates/_.example.org.key

Next, create symlinks for the certificate files.

Terminal window
mkdir /var/lib/jvlns
ln -s /var/lib/lego/certificates/_.${DOMAIN}.crt /etc/jvlns/certs/cert.crt
ln -s /var/lib/lego/certificates/_.${DOMAIN}.key /etc/jvlns/certs/cert.key

Lego should be run periodically to carry out automatic certificate renewal. Provided is an example of how to do this using systemd.

Start off by creating a systemd credential to store the deSEC API key.

Terminal window
mkdir -p /etc/systemd/system/renew-jvln-certificate.service.d
echo -n "<YOUR-DESEC-API-KEY>" | systemd-creds encrypt \
--name=desec-api-key \
- /etc/systemd/system/renew-jvln-certificate.service.d/desec-api-key.cred
chmod 600 /etc/systemd/system/renew-jvln-certificate.service.d/desec-api-key.cred

Then create the relevant files:

/etc/systemd/system/renew-jvln-certificate.service
[Unit]
Description=Renew Jvln Certificate
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
LoadCredentialEncrypted=desec-api-key:/etc/systemd/system/renew-jvln-certificate.service.d/desec-api-key.cred
ExecStart=/bin/sh -c 'DESEC_TOKEN=$(cat $CREDENTIALS_DIRECTORY/desec-api-key) \
/usr/local/bin/lego run \
--accept-tos \
--path /var/lib/lego \
--dns desec \
--dns.propagation.wait 120s \
-d "*.example.org" \
-d "example.org" \
--server letsencrypt'
/etc/systemd/system/renew-jvln-certificate.timer
[Unit]
Description=Weekly Renewal of Jvln Certificate
[Timer]
Persistent=true
OnCalendar=weekly
RandomizedDelaySec=6h
[Install]
WantedBy=timers.target

With this all in place, the systemd service can be started.

Terminal window
systemctl daemon-reload
systemctl enable --now renew-jvln-certificate.timer
# to check the timer is active
systemctl status renew-jvln-certificate.timer

Open a terminal and run the following command to install the server binary.

Terminal window
curl -fsSL https://codeberg.org/drmathias/jvln/raw/branch/main/scripts/install-server.sh | sh

The installer script does the following:

  • Installs the jvlns binary to your machine
  • Copies wwwroot to the expected path
  • Creates the default configuration file

The installation paths depends on your user.

User (standard) User ($XDG) Root
Binary ~/.local/bin/jvlns $XDG_BIN_HOME/jvlns /usr/local/bin/jvlns
Config ~/.config/jvlns/config.json $XDG_CONFIG_HOME/jvlns/config.json /etc/jvlns/config.json
Data ~/.local/share/jvlns/wwwroot $XDG_DATA_HOME/jvlns/wwwroot /usr/local/share/jvlns/wwwroot

The installer supports the following environment variables:

Variable Description Default
RELEASE Release tag to install latest
INSTALL_DIR Directory to install the binary into See above

With jvlns now installed and on your path, it is ready to run. You can simply run the following command to start the server.

Terminal window
jvlns serve

The server will start and begin listening for connections on the configured ports.

It is suggested to run jvlns as a systemd service. This allows you to isolate and monitor the process and makes it run on boot. To configure the service, create the service file.

/etc/systemd/system/jvlns.service
[Unit]
Description=Jvln Server
After=network.target
[Service]
ExecStart=/usr/local/bin/jvlns serve
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

Then run the following commands to start the service.

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now jvlns

With the server running, the only thing left to do is ensure it is reachable. Configure your DNS to ensure that the server is reachable via your domain.