gitit
gitit copied to clipboard
Add systemd service
It was proposed in https://github.com/tensor5/haskell-happstack/issues/11 to add systemd
service file to the haskell-gitit
Arch Linux package. We agreed that this issue should be discussed upstream.
We think that there should be two service files, one named gitit.service
:
[Unit]
Description=Gitit wiki
After=network.target
[Service]
ExecStart=/usr/bin/gitit -f /etc/gitit/default.conf
WorkingDirectory=/srv/gitit/default
User=gitit
Group=gitit
#Restart=on-failure
[Install]
WantedBy=multi-user.target
and the other named [email protected]
:
[Unit]
Description=Gitit wiki
After=network.target
[Service]
ExecStart=/usr/bin/gitit -f /etc/gitit/%I.conf
WorkingDirectory=/srv/gitit/%I
User=gitit
Group=gitit
#Restart=on-failure
[Install]
WantedBy=multi-user.target
with gitit
user and group being created upon installation and %I
being the unescaped instance name. User can enable mutliple instances by running e.g. systemctl start [email protected]
. Depending on the configuration it could run on port 80 (the executable /usr/bin/gitit
should be granted the capability CAP_NET_BIND_SERVICE
), or proxied behind a web server. The use of the directory /srv/gitit
as home of gitit
data is still being debated.
This is more a packaging issue, and I don't have strong opinions about it.
FYI here is a hardened gitit .service
that I just wrote.
It gets reverse-proxied by a nginx running on the same host (hence only localhost may talk to gitit directly).
This is working for me at least enough that chromium can log in and make edits to a page, with
$ ssh heavy -N -M -D12345 -oLocalCommand='chromium --temp-profile --proxy-server=socks://localhost:12345 http://heavy:5001 &' # NOTE: chromium won't allow "http://localhost:5001"
NOTE: For password resets: If you want gitit to use /usr/sbin/sendmail(8postfix) this is too aggressive (postfix needs set-gid maildrop!). If you want gitit to use /usr/sbin/sendmail(1msmtp) it will probably work because AF_INET6 and localhost are still unblocked.
NOTE: if your users don't "git push" changes to the gitit repo, you can ignore all the tmpfiles.d ACL crap, and you can turn on cache in gitit.conf. The CacheDirectory=%p means gitit will have write access to /var/cache/gitit implicitly, created and managed by systemd
- name: Be our Knowledge Base (KB).
tags: kb, gitit, wiki
block:
- ansible.builtin.package:
name:
- gitit
# gitit Recommends
- mime-support
- libghc-filestore-data
# Custom theme
# https://github.com/trentbuck/gitit-bootstrap-theme/
- gitit-bootstrap-theme
- name: tell systemd to create system user 'gitit'
ansible.builtin.copy:
dest: /etc/sysusers.d/cyber-gitit.conf
content: |
u gitit - - -
# FIXME: needs notify handler for "systemd-sysusers /etc/sysusers.d/cyber-gitit.conf"
- name: tell systemd to create grant user 'gitit' write access to KB repo
ansible.builtin.copy:
dest: /etc/tmpfiles.d/cyber-gitit.conf
content: |
# FIXME: this is excessive.
# FIXME: also needs "git config core.sharedRepository true", probably?
A /srv/vcs/kb - - - - default:user::rwx,user::rwx
A+ /srv/vcs/kb - - - - default:user:gitit:rwx,user:gitit:rwx
A+ /srv/vcs/kb - - - - default:group::rwx,group:gitit:rwx
A+ /srv/vcs/kb - - - - default:group:cyber:rwx,group:cyber:rwx
A+ /srv/vcs/kb - - - - default:other::---,other::---
- ansible.builtin.copy:
dest: /etc/systemd/system/gitit.service
content: |
[Service]
ExecStart=gitit --config-file=/etc/gitit.conf
[Install]
WantedBy=multi-user.target
# Hardening
[Service]
User=%p
LogsDirectory=%p
StateDirectory=%p
RuntimeDirectory=%p
WorkingDirectory=/run/%p
CacheDirectory=%p
ConfigurationDirectory=%p
ReadWritePaths=/srv/vcs/kb
# FIXME: gitit cannot listen on gitit.sock or systemd socket-activate yet.
# https://github.com/jgm/gitit/issues/675
# therefore we cannot do
# PrivateNetwork=yes
# RestrictAddressFamilies=~AF_INET
# RestrictAddressFamilies=~AF_INET6
# IPAddressDeny=any
CapabilityBoundingSet=
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
DevicePolicy=closed
IPAddressDeny=all
IPAddressAllow=localhost
NoNewPrivileges=yes
PrivateDevices=yes
PrivateUsers=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
RestrictSUIDGUID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
SystemCallFilter=~@resources
RestrictRealtime=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RemoveIPC=yes
UMask=0077
ProtectHostname=yes
ProcSubset=pid
- ansible.builtin.copy:
dest: /etc/gitit.conf
content: |
# See gitit --print-default-config for documentation.
default-page-type: RST
log-file: /var/log/gitit/gitit.log
# Use this to log every GET request.
# NOTE: if you do this, set up a logrotate rule for gitit!
#log-level: INFO
port: 5001
repository-path: /srv/vcs/kb
static-dir: /usr/share/javascript/gitit-bootstrap-theme/static
templates-dir: /usr/share/javascript/gitit-bootstrap-theme/templates
user-file: /var/lib/gitit/gitit-users
wiki-title: Knowledge Base
# FIXME: the cache doesn't know about updates made directly via git
# (as opposed to via the web UI). This could be fixed by having git
# delete the cached version of a file when its source is updated.
#use-cache: yes
cache-dir: /var/cache/gitit
# authentication-method: form
front-page: Knowledge Base
no-delete:
no-edit:
# Disable mathjax -- IMO we do not need to hotlink to cdnjs.cloudflare.com.
math: no
# A security thing. Probably on by default, but does not hurt to be explicit.
xss-sanitize: yes
- ansible.builtin.systemd:
daemon_reload: true
name: gitit.service
state: started
enabled: true
And here's systemd's assessment of systemd-provided hardening (anything below 4-5 is doing well; below 1 is nearly impossible):
NAME DESCRIPTION EXPOSURE
✗ PrivateNetwork= Service has access to the host's network 0.5
✓ User=/DynamicUser= Service runs under a static non-root user identity
✓ CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP) Service cannot change UID/GID identities/capabilities
✓ CapabilityBoundingSet=~CAP_SYS_ADMIN Service has no administrator privileges
✓ CapabilityBoundingSet=~CAP_SYS_PTRACE Service has no ptrace() debugging abilities
✗ RestrictAddressFamilies=~AF_(INET|INET6) Service may allocate Internet sockets 0.3
✓ RestrictNamespaces=~CLONE_NEWUSER Service cannot create user namespaces
✓ RestrictAddressFamilies=~… Service cannot allocate exotic sockets
✓ CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP) Service cannot change file ownership/access mode/capabilities
✓ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER) Service cannot override UNIX file/IPC permission checks
✓ CapabilityBoundingSet=~CAP_NET_ADMIN Service has no network configuration privileges
✓ CapabilityBoundingSet=~CAP_SYS_MODULE Service cannot load kernel modules
✓ CapabilityBoundingSet=~CAP_SYS_RAWIO Service has no raw I/O access
✓ CapabilityBoundingSet=~CAP_SYS_TIME Service processes cannot change the system clock
✗ DeviceAllow= Service has a device ACL with some special devices 0.1
✗ IPAddressDeny= Service does not define an IP address allow list 0.2
✓ KeyringMode= Service doesn't share key material with other services
✓ NoNewPrivileges= Service processes cannot acquire new privileges
✓ NotifyAccess= Service child processes cannot alter service state
✓ PrivateDevices= Service has no access to hardware devices
✓ PrivateMounts= Service cannot install system mounts
✓ PrivateTmp= Service has no access to other software's temporary files
✓ PrivateUsers= Service does not have access to other users
✓ ProtectClock= Service cannot write to the hardware clock or system clock
✓ ProtectControlGroups= Service cannot modify the control group file system
✓ ProtectHome= Service has no access to home directories
✓ ProtectKernelLogs= Service cannot read from or write to the kernel log ring buffer
✓ ProtectKernelModules= Service cannot load or read kernel modules
✓ ProtectKernelTunables= Service cannot alter kernel tunables (/proc/sys, …)
✓ ProtectProc= Service has restricted access to process tree (/proc hidepid=)
✓ ProtectSystem= Service has strict read-only access to the OS file hierarchy
✓ RestrictAddressFamilies=~AF_PACKET Service cannot allocate packet sockets
✗ RestrictSUIDSGID= Service may create SUID/SGID files 0.2
✓ SystemCallArchitectures= Service may execute system calls only with native ABI
✓ SystemCallFilter=~@clock System call allow list defined for service, and @clock is not included
✓ SystemCallFilter=~@debug System call allow list defined for service, and @debug is not included
✓ SystemCallFilter=~@module System call allow list defined for service, and @module is not included
✓ SystemCallFilter=~@mount System call allow list defined for service, and @mount is not included
✓ SystemCallFilter=~@raw-io System call allow list defined for service, and @raw-io is not included
✓ SystemCallFilter=~@reboot System call allow list defined for service, and @reboot is not included
✓ SystemCallFilter=~@swap System call allow list defined for service, and @swap is not included
✓ SystemCallFilter=~@privileged System call allow list defined for service, and @privileged is not included
✓ SystemCallFilter=~@resources System call allow list defined for service, and @resources is not included
✓ AmbientCapabilities= Service process does not receive ambient capabilities
✓ CapabilityBoundingSet=~CAP_AUDIT_* Service has no audit subsystem access
✓ CapabilityBoundingSet=~CAP_KILL Service cannot send UNIX signals to arbitrary processes
✓ CapabilityBoundingSet=~CAP_MKNOD Service cannot create device nodes
✓ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has no elevated networking privileges
✓ CapabilityBoundingSet=~CAP_SYSLOG Service has no access to kernel logging
✓ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE) Service has no privileges to change resource use parameters
✓ RestrictNamespaces=~CLONE_NEWCGROUP Service cannot create cgroup namespaces
✓ RestrictNamespaces=~CLONE_NEWIPC Service cannot create IPC namespaces
✓ RestrictNamespaces=~CLONE_NEWNET Service cannot create network namespaces
✓ RestrictNamespaces=~CLONE_NEWNS Service cannot create file system namespaces
✓ RestrictNamespaces=~CLONE_NEWPID Service cannot create process namespaces
✓ RestrictRealtime= Service realtime scheduling access is restricted
✓ SystemCallFilter=~@cpu-emulation System call allow list defined for service, and @cpu-emulation is not included
✓ SystemCallFilter=~@obsolete System call allow list defined for service, and @obsolete is not included
✗ RestrictAddressFamilies=~AF_NETLINK Service may allocate netlink sockets 0.1
✗ RootDirectory=/RootImage= Service runs within the host's root directory 0.1
✓ SupplementaryGroups= Service has no supplementary groups
✓ CapabilityBoundingSet=~CAP_MAC_* Service cannot adjust SMACK MAC
✓ CapabilityBoundingSet=~CAP_SYS_BOOT Service cannot issue reboot()
✓ Delegate= Service does not maintain its own delegated control group subtree
✓ LockPersonality= Service cannot change ABI personality
✓ MemoryDenyWriteExecute= Service cannot create writable executable memory mappings
✓ RemoveIPC= Service user cannot leave SysV IPC objects around
✓ RestrictNamespaces=~CLONE_NEWUTS Service cannot create hostname namespaces
✓ UMask= Files created by service are accessible only by service's own user by default
✓ CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE Service cannot mark files immutable
✓ CapabilityBoundingSet=~CAP_IPC_LOCK Service cannot lock memory into RAM
✓ CapabilityBoundingSet=~CAP_SYS_CHROOT Service cannot issue chroot()
✓ ProtectHostname= Service cannot change system host/domainname
✓ CapabilityBoundingSet=~CAP_BLOCK_SUSPEND Service cannot establish wake locks
✓ CapabilityBoundingSet=~CAP_LEASE Service cannot create file leases
✓ CapabilityBoundingSet=~CAP_SYS_PACCT Service cannot use acct()
✓ CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG Service cannot issue vhangup()
✓ CapabilityBoundingSet=~CAP_WAKE_ALARM Service cannot program timers that wake up the system
✗ RestrictAddressFamilies=~AF_UNIX Service may allocate local sockets 0.1
✓ ProcSubset= Service has no access to non-process /proc files (/proc subset=)
→ Overall exposure level for gitit.service: 1.3 OK 🙂