Setting up a simple systemd service

Setting up a simple systemd service

Disclaimer: Not an expert on either systemd or ansible, but this is something I may need to do again...

Recently I needed to test an haproxy setup with a service running on an arbitrary port. I didn't need anything fancy so decided to go with python's inbuilt http server.

This is a module that lets you serve the files in a directory over http.

From the command line something like:

python3 -m http.server 9999

That will run a server in the current working directory as the current user.

I needed to run this on several servers configured via ansible. These are RHEL 8 cloud image based servers.

The task ended up looking like:

    - name: 130 - Copy systemd service file to server  (7/23)
      become: yes
      ansible.builtin.template:
        src: files/templates/simple-http.service.j2
        dest: /etc/systemd/system/simple-http.service
        owner: root
        group: root
    - name: 140 - Simple HTTP Service (8/23)
      become: yes
      systemd:
        name: simple-http
        state: started
        daemon_reload: yes
        enabled: yes

These two tasks place a service file in the /etc/systemd/system directory and then start the service. I've specified daemon_reload to make sure any changes to the service file get picked up. In theory not necessary if you get the service file exactly right the first time, but I didn't and then spent some time wondering why my changes weren't being applied.

The service file template is:

[Unit]
Description=Simple http server for testing haproxy
After=multi-user.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/python3 -m http.server {{ha_backend_test_port}}
WantedBy=multi-user.target
WorkingDirectory=/home/cloud-user/

This defines a service that runs as root (not a good idea anywhere but a test environment that you can guarantee no untrusted users can access). The service runs in the cloud-user's home directory and will serve up an index.html file that ansible drops into that directory (without that index.html the server would list the files in the directory).

Next improvement to this will involve running this a less privileged user. Noting that cloud-user itself is not ideal because it has access to passwordless sudo. Not that there should be much chance of using http.server as an attack vector, but best to not make it any easier than we have to.

The parameter ha_backend_test_port is an ansible variable to set the actual port.

Testing this works is as simple as:

curl http://backend-01.example.com:8888
<html>
    <head>
        <title>Index</title>
    </head>
    <body>
        <h1>backend-01.example.com</h1>
    </body>
</html>

Assuming we specified 8888 as the ha_backend_test_port in our ansible.