There are numerous ways of deploying a Mojolicious app, so this is just one way. 0. Dependencies libmojolicious-perl pgc-db 1. Create a user to run the perl process. The name is at your discretion, here I'm using pgc-www. # adduser --no-create-home --home /var/www \ --shell /usr/sbin/nologin --disabled-login pgc-www 2. Configure postgres. Create a postgres user for pgc-www. # su - postgres $ createuser --connection-limit=10 --role=pgc_user pgc-www If you're using the simplest case, 'peer' authentication, then add a line in pg_ident.conf into the map you used for pgc-db. # MAPNAME SYSTEM-USERNAME PG-USERNAME ... ... ... irulanmap pgc-www pgc-www Tell postgres about your edit. # systemctl reload postgresql At this point, pgc-www should have access to the database. Test with # sudo -u pgc-www psql pg_book_catalog 3. Install the source code. # cd /opt # git clone https://tildegit.org/barnold/pgc-www.git At this point, the user 'pgc-www' should be able to run the app. Test with # sudo -u pgc-www morbo /opt/pgc-www/script/my_app and visit in your browser. 4. Optionally, provide a contact email address to site visitors. Add /opt/pgc-www/local-override.yml containing e.g. email-address: webmaster@example.net?Subject=Love your site! email-name: webmaster@example.net After you restart the app, your address should appear on the 'about' page. You can likewise place your own favicon.ico and robots.txt into public/. Entries for these are present in the supplied .gitignore so will be safe on updates. 5. Configure systemd to run the app under fastcgi, via socket activation. Suggested unit files follow, to go into /etc/systemd/system. = pgc.socket ================================ [Unit] Description = PG Catalog socket [Socket] Accept = false ListenStream = 127.0.0.1:8080 RestrictAddressFamilies = AF_INET [Install] WantedBy = sockets.target ============================================= = pgc.service =============================== # After edit, check syntax with # # systemd-analyze verify /etc/systemd/system/pgc.service # # and load the change with # # systemctl daemon-reload [Unit] Description = PG Catalog Requires = pgc.socket [Service] User = pgc-www Type = simple Environment = MOJO_MODE="production" ExecStart = /opt/pgc-www/script/my_app fastcgi StandardInput = socket StandardError = journal CapabilityBoundingSet = LockPersonality = yes MemoryDenyWriteExecute = yes NoNewPrivileges = yes PrivateDevices = yes PrivateNetwork = yes PrivateTmp = yes PrivateUsers = yes ProcSubset = pid ProtectClock = yes ProtectControlGroups = yes ProtectHome = yes ProtectHostname = yes ProtectKernelLogs = yes ProtectKernelModules = yes ProtectKernelTunables = yes ProtectProc = invisible ProtectSystem = strict RemoveIPC = yes RestrictAddressFamilies = AF_UNIX RestrictNamespaces = yes RestrictRealtime = yes RestrictSUIDSGID = yes SystemCallArchitectures = native SystemCallFilter = @system-service SystemCallFilter = ~ @privileged @resources UMask = 0066 [Install] WantedBy = default.target ============================================= Run # systemctl daemon-reload # systemctl start pgc.socket You can apply resource limits by running # systemctl set-property pgc.socket \ IPAddressAllow=localhost IPAddressDeny=any # systemctl set-property pgc.service \ CPUQuota=50% CPUWeight=50 MemoryHigh=128M MemoryMax=256M (The values for pgc.service are wild guesses.) Enable the service to start on boot. # systemctl enable pgc.socket 6. Configure your web server I use lighttpd and followed the guidance in . However, I disabled HTTP2 with server.feature-flags = ("server.h2proto" => "disable") because of sporadic trouble when using Firefox. Sometimes FF apparently fails to send the correct GET to follow a link, instead sending only a PRI. Possibly an instance of . Comments and questions are welcome at .