Install Plane Community Edition on Ubuntu 24.04 with HAProxy SSL Termination and Let’s Encrypt

Plane is a modern, open-source project management tool built for agile teams. In this guide, you’ll install the Plane Community Edition on a bare-metal Ubuntu 24.04 server, run it in Docker, and expose it securely through HAProxy 3.2 with SSL termination using Let’s Encrypt DNS challenge via Cloudflare.

This setup keeps Plane running over HTTP internally and handles TLS externally with HAProxy, while not requiring port 80 to be open publicly.


Prerequisites

  • Ubuntu 24.04 server
  • Domain name: plane.maksonlee.com, managed in Cloudflare
  • Public port 443 open (port 80 is not required)
  • Docker + Compose plugin installed: Install Docker on Ubuntu 24.04

Install required packages:

sudo apt update
sudo apt install -y certbot python3-certbot-dns-cloudflare
sudo add-apt-repository ppa:vbernat/haproxy-3.2 -y
sudo apt-get install haproxy=3.2.\*
sudo systemctl enable --now haproxy

  1. Install Plane Community Edition
cd ~
mkdir plane-selfhost
cd plane-selfhost
curl -fsSL -o setup.sh https://github.com/makeplane/plane/releases/latest/download/setup.sh
chmod a+x setup.sh
./setup.sh install
cd ~
sudo mv plane-selfhost /opt/

  1. Configure Plane Environment for HTTPS Awareness

Edit the generated plane.env file:

vi /opt/plane-selfhost/plane-app/plane.env

Update the following values:

APP_DOMAIN=plane.maksonlee.com
WEB_URL=https://plane.maksonlee.com
CORS_ALLOWED_ORIGINS=https://plane.maksonlee.com

  1. Issue HTTPS Certificate via Cloudflare DNS

Create Cloudflare credentials:

mkdir -p ~/.secrets/certbot
vi ~/.secrets/certbot/cloudflare.ini

Add:

dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

Secure the file:

chmod 600 ~/.secrets/certbot/cloudflare.ini

Request certificate:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
  -d plane.maksonlee.com

  1. Bundle Certificate for HAProxy
sudo mkdir -p /etc/haproxy/certs/
sudo bash -c "cat /etc/letsencrypt/live/plane.maksonlee.com/fullchain.pem \
  /etc/letsencrypt/live/plane.maksonlee.com/privkey.pem \
  > /etc/haproxy/certs/plane.maksonlee.com.pem"
sudo chmod 600 /etc/haproxy/certs/plane.maksonlee.com.pem

  1. Configure HAProxy for SSL Termination

Edit /etc/haproxy/haproxy.cfg:

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
    mode http
    default_backend plane
 
backend plane
    mode http
    option http-buffer-request
    option http-keep-alive
    option forwardfor
    http-request set-header X-Forwarded-Proto https
 
    server plane1 127.0.0.1:80

Restart HAProxy:

sudo systemctl restart haproxy

  1. Automate Certificate Renewal

Create deploy hook to reload HAProxy on renewal:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh > /dev/null <<EOF
#!/bin/bash
cat /etc/letsencrypt/live/plane.maksonlee.com/fullchain.pem \
    /etc/letsencrypt/live/plane.maksonlee.com/privkey.pem \
    > /etc/haproxy/certs/plane.maksonlee.com.pem
systemctl reload haproxy
EOF
 
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh

Test renewal:

sudo certbot renew --dry-run

  1. Create a systemd Service for Plane

Create the /etc/systemd/system/plane.service service file:

[Unit]
Description=Plane
After=network-online.target docker.service
Requires=docker.service
 
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/plane-selfhost
ExecStart=/opt/plane-selfhost/setup.sh start
ExecStop=/opt/plane-selfhost/setup.sh stop
TimeoutStartSec=0
 
[Install]
WantedBy=multi-user.target

Enable and start it:

sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable --now plane

  1. Access Plane

Visit https://plane.maksonlee.com and you’ll see the setup UI:

Welcome Screen

Setup Admin

Login

Onboarding

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top