diff --git a/defaults/main.yml b/defaults/main.yml
index 7748243cc79286ef832ba63c4a3d8d736ecdf646..206df3a2cc7335b6356565e0367b642a74ab8a58 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -16,3 +16,5 @@ funkwhale_api_ip: 127.0.0.1
 funkwhale_api_port: 5000
 funkwhale_settings_module: config.settings.production
 funkwhale_env_vars: []
+funkwhale_systemd_after: redis.service postgresql.service
+funkwhale_systemd_service_name: funkwhale
diff --git a/handlers/main.yml b/handlers/main.yml
index b8ce0f3ba453b58f0b07470dcb218f3c7a440e13..c548e0313c4ec0c21851e41e8f9d5d09739d4eaf 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,2 +1,5 @@
 ---
-# handlers file for funkwhale
+- name: restart funkwhale
+  service:
+    name: funkwhale.target
+    state: restarted
diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py
index 613d9753c7a7bc264fe49055a2de58d514c0ca95..9adad386d80fe9e38f100d5baae0f3e7df351003 100644
--- a/molecule/default/tests/test_default.py
+++ b/molecule/default/tests/test_default.py
@@ -119,3 +119,13 @@ def test_migrations_applied(host):
     """
     result = host.run(cmd)
     assert result.stdout == "1"
+
+
+@pytest.mark.parametrize(
+    "service",
+    ["funkwhale-server", "funkwhale-worker", "funkwhale-beat", "funkwhale.target"],
+)
+def test_funkwhale_services(service, host):
+    service = host.service(service)
+    assert service.is_running
+    assert service.is_enabled
diff --git a/tasks/funkwhale.yml b/tasks/funkwhale.yml
index 0e0ea955345628f674c0f7a913fe27ea687e052a..f67d9ff02e5c9b76e6b81bd561827343d4a885ff 100644
--- a/tasks/funkwhale.yml
+++ b/tasks/funkwhale.yml
@@ -55,6 +55,8 @@
     mode: 0600
   vars:
     django_secret_key: "{{ secret_key['content'] | b64decode }}"
+  notify:
+    - restart funkwhale
 
 - name: Download front-end files
   become: true
@@ -63,7 +65,8 @@
     src: https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/{{ funkwhale_version }}/download?job=build_front
     dest: "{{ funkwhale_install_path }}"
     remote_src: true
-
+  notify:
+    - restart funkwhale
 
 - name: Download api files
   become: true
@@ -72,6 +75,8 @@
     src: https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/{{ funkwhale_version }}/download?job=build_api
     dest: "{{ funkwhale_install_path }}"
     remote_src: true
+  notify:
+    - restart funkwhale
 
 - name: "Setup virtualenv"
   become: true
@@ -81,7 +86,6 @@
     virtualenv: "{{ funkwhale_install_path }}/virtualenv"
     virtualenv_python: python3
 
-
 - name: "Install python dependencies"
   become: true
   become_user: "{{ funkwhale_username }}"
@@ -89,7 +93,8 @@
     requirements: "{{ funkwhale_install_path }}/api/requirements.txt"
     virtualenv: "{{ funkwhale_install_path }}/virtualenv"
     virtualenv_python: python3
-
+  notify:
+    - restart funkwhale
 
 - name: "Collect static files"
   command: "{{ funkwhale_install_path }}/virtualenv/bin/python api/manage.py collectstatic --no-input"
@@ -98,7 +103,6 @@
   args:
     chdir: "{{ funkwhale_install_path }}"
 
-
 - name: "Apply database migrations"
   become: true
   become_user: "{{ funkwhale_username }}"
diff --git a/tasks/main.yml b/tasks/main.yml
index f22e3acfdf026f4975466fc166ba2dc50df76ad4..8e071067a72421417fc108833d7cde9db41120c5 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,6 +1,7 @@
 ---
-# - include: packages.yml
-# - include: db.yml
-# - include: redis.yml
+- include: packages.yml
+- include: db.yml
+- include: redis.yml
 - include: funkwhale.yml
+- include: services.yml
 - include: nginx.yml
diff --git a/tasks/services.yml b/tasks/services.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6ad7d58667956539929fbbcfe74ebacf93dd61dc
--- /dev/null
+++ b/tasks/services.yml
@@ -0,0 +1,42 @@
+---
+
+- name: "Create {{ funkwhale_systemd_service_name }}-* systemd file"
+  become: true
+  template:
+    src: "funkwhale-process.service"
+    dest: "/etc/systemd/system/{{ funkwhale_systemd_service_name }}-{{ item.name }}.service"
+    mode: 0600
+  with_items:
+    - name: worker
+      description: Funkwhale celery worker
+      command: "{{ funkwhale_install_path }}/virtualenv/bin/celery -A funkwhale_api.taskapp worker -l INFO"
+    - name: server
+      description: Funkwhale application server
+      command: "{{ funkwhale_install_path }}/virtualenv/bin/daphne -b ${FUNKWHALE_API_IP} -p ${FUNKWHALE_API_PORT} config.asgi:application --proxy-headers"
+    - name: beat
+      description: Funkwhale celery beat process
+      command: "{{ funkwhale_install_path }}/virtualenv/bin/celery -A funkwhale_api.taskapp beat -l INFO"
+  notify:
+    - restart funkwhale
+
+- name: "Create {{ funkwhale_systemd_service_name }} systemd target file"
+  become: true
+  template:
+    src: "{{ funkwhale_systemd_service_name }}.target"
+    dest: "/etc/systemd/system/{{ funkwhale_systemd_service_name }}.target"
+    mode: 0600
+  notify:
+    - restart funkwhale
+
+- name: "Start and enable {{ funkwhale_systemd_service_name }}-* services"
+  when: funkwhale_nginx_managed
+  systemd:
+    name: "{{ item }}"
+    enabled: true
+    daemon_reload: true
+    state: started
+  with_items:
+    - "{{ funkwhale_systemd_service_name }}.target"
+    - "{{ funkwhale_systemd_service_name }}-worker.service"
+    - "{{ funkwhale_systemd_service_name }}-server.service"
+    - "{{ funkwhale_systemd_service_name }}-beat.service"
diff --git a/templates/env.j2 b/templates/env.j2
index d4d42df9f099fc5bc6b225c8682e009b38979524..4ef1f91f1553194f165b90af4cb608ab3b1423cf 100644
--- a/templates/env.j2
+++ b/templates/env.j2
@@ -1,5 +1,4 @@
-{{ ansible_managed }}
-
+# {{ ansible_managed }}
 
 FUNKWHALE_HOSTNAME={{ funkwhale_hostname }}
 FUNKWHALE_PROTOCOL={{ funkwhale_protocol }}
diff --git a/templates/funkwhale-process.service b/templates/funkwhale-process.service
new file mode 100644
index 0000000000000000000000000000000000000000..d1c6f45d4bba1b34bd76324df25994c9fe11e94c
--- /dev/null
+++ b/templates/funkwhale-process.service
@@ -0,0 +1,14 @@
+# {{ ansible_managed }}
+[Unit]
+Description={{ item.description }}
+After={{ funkwhale_systemd_after }}
+PartOf={{ funkwhale_systemd_service_name }}.target
+
+[Service]
+User={{ funkwhale_username }}
+WorkingDirectory={{ funkwhale_install_path }}/api
+EnvironmentFile={{ funkwhale_config_path }}/.env
+ExecStart={{ item.command }}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/templates/funkwhale.target b/templates/funkwhale.target
new file mode 100644
index 0000000000000000000000000000000000000000..cd2133e18f228df8fa3ea8bf27c73e0c1e6a4f01
--- /dev/null
+++ b/templates/funkwhale.target
@@ -0,0 +1,3 @@
+[Unit]
+Description=Funkwhale
+Wants={{ funkwhale_systemd_service_name }}-server.service {{ funkwhale_systemd_service_name }}-worker.service {{ funkwhale_systemd_service_name }}-beat.service