{%- set rw = gitea._rw + [ gitea.lookup.paths.conf | path_join("app.ini") ] -%} {%- set needs_port_cap = gitea.config | traverse("server:http_port", 3000) < 1024 or ( not gitea.config | traverse("server:disable_ssh", false) and gitea.config | traverse("server:start_ssh_server", false) and gitea.config | traverse("server:ssh_port", 22) < 1024 ) -%} {%- set needs_custom = gitea.lookup.paths.custom != (gitea.lookup.paths.work | path_join('custom')) -%} # https://github.com/archlinux/svntogit-community/blob/3474a4abbfa932796b33cf5d11d9e5312cebec1a/trunk/gitea.service [Unit] Description=Gitea (Git with a cup of tea) Documentation=https://docs.gitea.io/en-us/ After=network.target {%- if gitea.service.socket_activation %} After={{ gitea.lookup.service.name }}.main.socket Requires={{ gitea.lookup.service.name }}.main.socket {%- endif %} {%- if gitea.service.wants %} {%- for wanted in gitea.service.wants %} Wants={{ wanted }}{{ ".service" if "." not in wanted }} After={{ wanted }}{{ ".service" if "." not in wanted }} {%- endfor %} {%- endif %} {%- if gitea.service.requires_mount %} {%- for mount in gitea.service.requires_mount %} RequiresMountsFor={{ mount }} {%- endfor %} {%- endif %} [Service] ExecStart={{ gitea.lookup.paths.bin | path_join("gitea") }} web --config '{{ gitea.lookup.paths.conf | path_join("app.ini") }}' Environment=USER={{ gitea.lookup.user }} HOME={{ gitea.lookup.paths.work }} GITEA_WORK_DIR={{ gitea.lookup.paths.work }} {%- if needs_custom %} GITEA_CUSTOM={{ gitea.lookup.paths.custom }}{%- endif %} # Process management #################### Type=simple Restart=always RestartSec=2s # Directory creation and permissions #################################### User={{ gitea.lookup.user }} Group={{ gitea.lookup.group }} WorkingDirectory={{ gitea.lookup.paths.work }} {%- if "unix" in gitea.config | traverse("server:protocol", "") %} RuntimeDirectory=gitea {%- endif %} {%- if "file" in gitea.config | traverse("log:mode", "console") %} {%- if "/var/log/gitea" == gitea.lookup.paths.log %} LogsDirectory=gitea {%- else %} {%- do rw.append(gitea.lookup.paths.log) %} {%- endif %} {%- endif %} {%- if "/var/lib/gitea" == gitea.lookup.paths.work %} StateDirectory=gitea {%- else %} {%- do rw.append(gitea.lookup.paths.work) %} {%- endif %} ReadWritePaths={{ rw | join(" ") }} # Hardening measures #################### # https://wiki.archlinux.org/title/Gitea#Binding_on_restricted_ports AmbientCapabilities={{ "CAP_NET_BIND_SERVICE" if needs_port_cap }} CapabilityBoundingSet={{ "CAP_NET_BIND_SERVICE" if needs_port_cap }} PrivateUsers={{ (not needs_port_cap) | string | lower }} LockPersonality=true # Required by commit search #MemoryDenyWriteExecute=true NoNewPrivileges=True #SecureBits=noroot-locked PrivateDevices=true PrivateTmp=true ProtectClock=true ProtectControlGroups=true ProtectHome=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectProc=invisible ProtectSystem=strict RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX RestrictNamespaces=true RestrictRealtime=true RestrictSUIDSGID=true SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallErrorNumber=EPERM [Install] WantedBy=multi-user.target