Skip to content

Instantly share code, notes, and snippets.

@CaedenPH
Last active October 28, 2022 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CaedenPH/715acf7dfb3458659edb49db034a2145 to your computer and use it in GitHub Desktop.
Save CaedenPH/715acf7dfb3458659edb49db034a2145 to your computer and use it in GitHub Desktop.
Script to make a systemd unit and host it on nginx from project (linux)

Usage

Prequisites

  1. Python 3.10 and above is required
sudo apt-get install python3
  1. Nginx must be installed
sudo apt-get install nginx

Create config.json

This file will be read by the python script and parsed, with each $name key being another server. Replace $variable with your information.

{
  "$name": {
    "directory": "$directory",
    "script": "$script",
    "domains": "$domains"
  }
}
  • $name - The short name that will be used to make the service and proxy
  • $directory - The working directory of the website

Note: Please set this value to the absoute path of the directory

  • $script - The script that will be ran in order to host the website

Note: You must add a port option and set the value to {port}. This will later be dynamically formatted

  • $domains - The domains that your website will be published on

Note: for the domains to work, you must point an A record to the ip address of your server

Run main.py

This will recursively go through your local config.json file, and set up each key as a systemd unit and nginx proxy

sudo python3 main.py

Note: Because this file will modify files within the /etc/ directory, the file must run as root, the script being ran with sudo Will execute the main script and apply

Theory

The main.py script will iterate through every server config and sets up each config.

Example config

{
  "example": {
    "directory": "/home/ubuntu/example/dist",
    "script": "/usr/bin/npx http-server --port {port}",
    "domains": ["example.com", "www.example.com"]
  }
}

Steps

  1. The script will create a file in /etc/systemd/system/ named example.service with content
[Unit]
Description=Start example server
After=network-online.target
Requires=network-online.target

[Service]
Type=simple
RemainAfterExit=yes
ExecStartPre=sleep 5
ExecStartPre=/usr/bin/git stash
ExecStartPre=/usr/bin/git pull
ExecStart=/usr/bin/npx http-server --port 5000
WorkingDirectory=/home/ubuntu/example/dist
User=ubuntu

[Install]
WantedBy=multi-user.target
  1. This service will be enabled and started with the commands
sudo systemctl enable example.service
sudo systemctl start example.service
  1. Next, the proxy will be created in /etc/nginx/sites-available with this content
server {
  listen 80;
  listen [::]:80;
  
  server_name example.com www.example.com;
  
  location / {
    proxy_pass http://127.0.0.1:5000;
    include proxy_params;
  }
}
  1. This will then be symlinked to /etc/nginx/sites-enabled with the command
sudo ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled`
  1. The proxy will then be enabled with
sudo systemctl restart nginx.service
"""
Recursively iterates through every server config in the local config.json file
and sets up a systemd unit and nginx proxy based off of the given server config.
"""
import json
import re
import subprocess
import os
_UNIT_FILE = """
[Unit]
Description=Start example server
After=network-online.target
Requires=network-online.target
[Service]
Type=simple
RemainAfterExit=yes
ExecStartPre=sleep 5
ExecStartPre=/usr/bin/git stash
ExecStartPre=/usr/bin/git pull
ExecStart={script}
WorkingDirectory={directory}
User={user}
[Install]
WantedBy=multi-user.target
"""
_NGINX_PROXY = """
server {{
listen 80;
listen [::]:80;
server_name {domains};
location / {{
proxy_pass http://127.0.0.1:{port};
include proxy_params;
}}
}}
"""
class Server:
def __init__(self, server: str) -> None:
self.server = server
def create_unit(self, *, script: str, directory: str) -> None:
with open(f"/etc/systemd/system/{self.server}.service", "w") as service:
service.write(
_UNIT_FILE.format(
script=script,
directory=directory,
user=re.findall(r"/home/(.*?)/", directory)[0],
)
)
subprocess.run(f"sudo systemctl enable {self.server}.service", shell=True)
subprocess.run(f"sudo systemctl start {self.server}.service", shell=True)
def create_nginx_proxy(self, *, domains: list[str], port: str) -> None:
with open(f"/etc/nginx/sites-available/{self.server}", "w") as proxy:
proxy.write(_NGINX_PROXY.format(domains=" ".join(domains), port=port))
subprocess.run(
f"sudo ln -s /etc/nginx/sites-available/{self.server} /etc/nginx/sites-enabled",
shell=True
)
subprocess.run("sudo systemctl restart nginx.service", shell=True)
def main(config: dict[str, dict[str, str | list[str]]]) -> None:
for i, (server_name, server_config) in enumerate(config.items()):
directory, script, domains = server_config.values()
server = Server(server_name)
server.create_unit(script=script.format(port=9000 + i), directory=directory)
server.create_nginx_proxy(domains=domains, port=9000 + i)
if __name__ == "__main__":
with open("config.json") as cfg:
config = json.load(cfg)
main(config)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment