Twenty deployment on podman

Does twentycrm support deployment with podman? I see two possible approaches: A: Use (or modify and use) the docker-compose.yml with podman-compose. B: Manually build a podman pod containing each of the containers for twenty as specified in docker-compose.yml What would be the recommended approach to running twenty under podman? I am currently experimenting with both... And keep getting stuck various places.... My aim with this thread is to have a single place to document what works and what doesn't with regards to deploying twenty on podman as well as to hopefully get help from others who have actual experience witht his.
3 Replies
EbenezerIbiza
EbenezerIbizaOP4d ago
Here is my script for approach B so far:
export POSTGRES_PASSWORD="secret"
export APP_SECRET="secret"
export SERVER_URL="https://example.com

podman volume create twenty-db-data
podman volume create twenty-server-data
podman volume create twenty-redis-data

podman pod create --name twenty-pod -p 127.0.0.1:8080:3000

podman run -d --pod twenty-pod --name twenty-db \
-e POSTGRES_DB=twenty \
-e POSTGRES_USER=twenty \
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
-v twenty-db-data:/var/lib/postgresql/data:Z \
docker.io/library/postgres:16

podman run -d --pod twenty-pod --name twenty-redis \
-v twenty-redis-data:/data:Z \
docker.io/library/redis:latest

podman run -d --pod twenty-pod --name twenty-server \
-e NODE_PORT=3000 \
-e SERVER_URL="$SERVER_URL" \
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
-e REDIS_URL="redis://twenty-redis:6379" \
-e APP_SECRET="$APP_SECRET" \
-e NODE_ENV=production \
-e LOG_LEVEL=info \
-v twenty-server-data:/app/docker-data:Z \
docker.io/twentycrm/twenty:latest

podman run -d --pod twenty-pod --name twenty-worker \
--init \
-e SERVER_URL="$SERVER_URL" \
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
-e REDIS_URL="redis://twenty-redis:6379" \
-e APP_SECRET="$APP_SECRET" \
-e DISABLE_DB_MIGRATIONS=true \
-e NODE_ENV=production \
-e LOG_LEVEL=info \
-v twenty-server-data:/app/docker-data:Z \
docker.io/twentycrm/twenty:latest \
yarn worker:prod

# wait some time, check status
podman ps --pod -f name=twenty-pod
export POSTGRES_PASSWORD="secret"
export APP_SECRET="secret"
export SERVER_URL="https://example.com

podman volume create twenty-db-data
podman volume create twenty-server-data
podman volume create twenty-redis-data

podman pod create --name twenty-pod -p 127.0.0.1:8080:3000

podman run -d --pod twenty-pod --name twenty-db \
-e POSTGRES_DB=twenty \
-e POSTGRES_USER=twenty \
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
-v twenty-db-data:/var/lib/postgresql/data:Z \
docker.io/library/postgres:16

podman run -d --pod twenty-pod --name twenty-redis \
-v twenty-redis-data:/data:Z \
docker.io/library/redis:latest

podman run -d --pod twenty-pod --name twenty-server \
-e NODE_PORT=3000 \
-e SERVER_URL="$SERVER_URL" \
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
-e REDIS_URL="redis://twenty-redis:6379" \
-e APP_SECRET="$APP_SECRET" \
-e NODE_ENV=production \
-e LOG_LEVEL=info \
-v twenty-server-data:/app/docker-data:Z \
docker.io/twentycrm/twenty:latest

podman run -d --pod twenty-pod --name twenty-worker \
--init \
-e SERVER_URL="$SERVER_URL" \
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
-e REDIS_URL="redis://twenty-redis:6379" \
-e APP_SECRET="$APP_SECRET" \
-e DISABLE_DB_MIGRATIONS=true \
-e NODE_ENV=production \
-e LOG_LEVEL=info \
-v twenty-server-data:/app/docker-data:Z \
docker.io/twentycrm/twenty:latest \
yarn worker:prod

# wait some time, check status
podman ps --pod -f name=twenty-pod
For some reason the pod does not show up. This is the podman container ps after running this:
$ podman container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0314bdcdbf4d docker.io/library/registry:2 /etc/docker/regis... 43 hours ago Up 43 hours ago 127.0.0.1:5000->5000/tcp registry
3b9194a57f41 localhost/podman-pause:4.3.1-0 7 minutes ago Up 7 minutes ago 127.0.0.1:8080->3000/tcp a39cf43dee9a-infra
cc689016d620 docker.io/library/postgres:16 postgres 7 minutes ago Up 7 minutes ago 127.0.0.1:8080->3000/tcp twenty-db
a67cfaae11c9 docker.io/library/redis:latest redis-server 6 minutes ago Up 6 minutes ago 127.0.0.1:8080->3000/tcp twenty-redis
0812602bfe83 docker.io/twentycrm/twenty:latest node dist/src/mai... 6 minutes ago Up 6 minutes ago 127.0.0.1:8080->3000/tcp twenty-server
7b09d27e2a1f docker.io/twentycrm/twenty:latest yarn worker:prod 6 minutes ago Up 5 minutes ago 127.0.0.1:8080->3000/tcp twenty-worker
$ podman container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0314bdcdbf4d docker.io/library/registry:2 /etc/docker/regis... 43 hours ago Up 43 hours ago 127.0.0.1:5000->5000/tcp registry
3b9194a57f41 localhost/podman-pause:4.3.1-0 7 minutes ago Up 7 minutes ago 127.0.0.1:8080->3000/tcp a39cf43dee9a-infra
cc689016d620 docker.io/library/postgres:16 postgres 7 minutes ago Up 7 minutes ago 127.0.0.1:8080->3000/tcp twenty-db
a67cfaae11c9 docker.io/library/redis:latest redis-server 6 minutes ago Up 6 minutes ago 127.0.0.1:8080->3000/tcp twenty-redis
0812602bfe83 docker.io/twentycrm/twenty:latest node dist/src/mai... 6 minutes ago Up 6 minutes ago 127.0.0.1:8080->3000/tcp twenty-server
7b09d27e2a1f docker.io/twentycrm/twenty:latest yarn worker:prod 6 minutes ago Up 5 minutes ago 127.0.0.1:8080->3000/tcp twenty-worker
Here are the last 6 lines of container logs for all the containers: https://paste.yt/p28725.html (paste too big for discord) I think this actually looks OK. But not sure why the pod never gets ready... I think it actually is running OK afterall 😅
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
a39cf43dee9a twenty-pod Running 24 minutes ago 3b9194a57f41 5
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
a39cf43dee9a twenty-pod Running 24 minutes ago 3b9194a57f41 5
Will now go ahead and try to configure ingress Additionally, I install this as a systemd service:
[Unit]
Description=TwentyCRM Podman Pod
After=network.target

[Service]
Type=oneshot
WorkingDirectory=/home/apprunner/apps/twenty
ExecStart=/home/apprunner/apps/twenty/start
ExecStop=/usr/bin/podman pod stop twenty-pod
RemainAfterExit=yes

[Install]
WantedBy=default.target
[Unit]
Description=TwentyCRM Podman Pod
After=network.target

[Service]
Type=oneshot
WorkingDirectory=/home/apprunner/apps/twenty
ExecStart=/home/apprunner/apps/twenty/start
ExecStop=/usr/bin/podman pod stop twenty-pod
RemainAfterExit=yes

[Install]
WantedBy=default.target
mkdir -p ~/.config/systemd/user
cp twentycrm.service ~/.config/systemd/user

systemctl --user daemon-reload
systemctl --user enable twentycrm.service
systemctl --user start twentycrm.service
mkdir -p ~/.config/systemd/user
cp twentycrm.service ~/.config/systemd/user

systemctl --user daemon-reload
systemctl --user enable twentycrm.service
systemctl --user start twentycrm.service
OK. I got the ingress set up (using nginx) Basically just adding this site:
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
server_name example.com;

location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
server_name example.com;

location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
Get the certs from certbot/LE. I now seem to have a working twenty. So I guess the above might work as a HOWTO on how to set up twenty with podman. Next step is to put this in a podman-compose.yml Here is a working podman-compose.yml
version: "3.8"

services:
db:
container_name: twenty-db
image: postgres:16
environment:
POSTGRES_DB: twenty
POSTGRES_USER: twenty
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- twenty-db-data:/var/lib/postgresql/data:Z

redis:
container_name: twenty-redis
image: redis:latest
volumes:
- twenty-redis-data:/data:Z

server:
container_name: twenty-server
image: twentycrm/twenty:latest
environment:
NODE_PORT: "3000"
SERVER_URL: ${SERVER_URL}
PG_DATABASE_URL: "postgresql://twenty:${POSTGRES_PASSWORD}@twenty-db:5432/twenty"
REDIS_URL: "redis://twenty-redis:6379"
APP_SECRET: ${APP_SECRET}
NODE_ENV: production
LOG_LEVEL: info
volumes:
- twenty-server-data:/app/docker-data:Z
ports:
- 127.0.0.1:8080:3000

worker:
container_name: twenty-worker
image: twentycrm/twenty:latest
command: yarn worker:prod
environment:
SERVER_URL: ${SERVER_URL}
PG_DATABASE_URL: "postgresql://twenty:${POSTGRES_PASSWORD}@twenty-db:5432/twenty"
REDIS_URL: "redis://twenty-redis:6379"
APP_SECRET: ${APP_SECRET}
DISABLE_DB_MIGRATIONS: "true"
NODE_ENV: production
LOG_LEVEL: info
volumes:
- twenty-server-data:/app/docker-data:Z
init: true

volumes:
twenty-db-data:
twenty-server-data:
twenty-redis-data:
version: "3.8"

services:
db:
container_name: twenty-db
image: postgres:16
environment:
POSTGRES_DB: twenty
POSTGRES_USER: twenty
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- twenty-db-data:/var/lib/postgresql/data:Z

redis:
container_name: twenty-redis
image: redis:latest
volumes:
- twenty-redis-data:/data:Z

server:
container_name: twenty-server
image: twentycrm/twenty:latest
environment:
NODE_PORT: "3000"
SERVER_URL: ${SERVER_URL}
PG_DATABASE_URL: "postgresql://twenty:${POSTGRES_PASSWORD}@twenty-db:5432/twenty"
REDIS_URL: "redis://twenty-redis:6379"
APP_SECRET: ${APP_SECRET}
NODE_ENV: production
LOG_LEVEL: info
volumes:
- twenty-server-data:/app/docker-data:Z
ports:
- 127.0.0.1:8080:3000

worker:
container_name: twenty-worker
image: twentycrm/twenty:latest
command: yarn worker:prod
environment:
SERVER_URL: ${SERVER_URL}
PG_DATABASE_URL: "postgresql://twenty:${POSTGRES_PASSWORD}@twenty-db:5432/twenty"
REDIS_URL: "redis://twenty-redis:6379"
APP_SECRET: ${APP_SECRET}
DISABLE_DB_MIGRATIONS: "true"
NODE_ENV: production
LOG_LEVEL: info
volumes:
- twenty-server-data:/app/docker-data:Z
init: true

volumes:
twenty-db-data:
twenty-server-data:
twenty-redis-data:
charles
charles3d ago
GitHub
Added support for podman deployment by thomasdn · Pull Request #11...
Added files needed to deploy twenty on podman using podman-compose.
charles
charles3d ago
ty!

Did you find this page helpful?