mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Joseph Nuthalapati <njoseph@riseup.net>
196 lines
4.9 KiB
Python
Executable File
196 lines
4.9 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Configuration helper for infinoted.
|
|
"""
|
|
|
|
import argparse
|
|
import grp
|
|
import os
|
|
import pwd
|
|
import shutil
|
|
import subprocess
|
|
import time
|
|
|
|
from plinth import action_utils
|
|
|
|
DATA_DIR = '/var/lib/infinoted'
|
|
KEY_DIR = '/etc/infinoted'
|
|
SYNC_DIR = os.path.join(DATA_DIR, 'sync')
|
|
|
|
CONF_PATH = '/etc/xdg/infinoted.conf'
|
|
CONF = f'''
|
|
[infinoted]
|
|
|
|
# Possible values : no-tls, allow-tls, require-tls
|
|
security-policy=require-tls
|
|
|
|
# Absolute path of the certificate file.
|
|
certificate-file=/etc/infinoted/infinoted-cert.pem
|
|
|
|
# Absolute path of the private key file.
|
|
key-file=/etc/infinoted/infinoted-key.pem
|
|
|
|
# Enable plugins
|
|
plugins=note-text;autosave;logging;directory-sync
|
|
|
|
# Specify a path to use a root certificate instead of a certificate-key pair.
|
|
#certificate-chain=
|
|
|
|
#password=
|
|
|
|
# Automatically save documents every few seconds
|
|
[autosave]
|
|
|
|
# Setting this to 0 disables autosave.
|
|
interval=60
|
|
|
|
# Synchronize files to another directory in plain text format
|
|
[directory-sync]
|
|
|
|
# Directory to sync plain text files
|
|
directory={SYNC_DIR}
|
|
|
|
# Synchronize seconds
|
|
interval=60
|
|
|
|
# Log additional events
|
|
[logging]
|
|
|
|
# Log when users connect or disconnect
|
|
log-connections=true
|
|
|
|
# Log errors with client connections such as a connection reset
|
|
log-connection-errors=true
|
|
'''
|
|
|
|
SYSTEMD_SERVICE_PATH = '/etc/systemd/system/infinoted.service'
|
|
SYSTEMD_SERVICE = '''
|
|
#
|
|
# This file is managed and overwritten by Plinth. If you wish to edit
|
|
# it, disable infinoted in Plinth, remove this file and manage it manually.
|
|
#
|
|
|
|
[Unit]
|
|
Description=collaborative text editor service
|
|
Documentation=man:infinoted(1)
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=infinoted
|
|
Group=infinoted
|
|
ExecStart=/usr/bin/infinoted
|
|
ConfigurationDirectory=infinoted
|
|
ConfigurationDirectoryMode=0750
|
|
LockPersonality=yes
|
|
NoNewPrivileges=yes
|
|
PrivateDevices=yes
|
|
PrivateMounts=yes
|
|
PrivateTmp=yes
|
|
ProtectControlGroups=yes
|
|
ProtectHome=yes
|
|
ProtectKernelLogs=yes
|
|
ProtectKernelModules=yes
|
|
ProtectKernelTunables=yes
|
|
ProtectSystem=full
|
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
|
RestrictRealtime=yes
|
|
StateDirectory=infinoted
|
|
SystemCallArchitectures=native
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
'''
|
|
|
|
|
|
def parse_arguments():
|
|
"""Return parsed command line arguments as dictionary."""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
|
|
|
subparsers.add_parser('setup', help='Configure infinoted after install')
|
|
|
|
subparsers.required = True
|
|
return parser.parse_args()
|
|
|
|
|
|
def _kill_daemon():
|
|
"""Try to kill the infinoted daemon for upto 5 minutes."""
|
|
end_time = time.time() + 300
|
|
while time.time() < end_time:
|
|
try:
|
|
subprocess.run(['infinoted', '--kill-daemon'], check=True)
|
|
break
|
|
except subprocess.CalledProcessError:
|
|
pass
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
def subcommand_setup(_):
|
|
"""Configure infinoted after install."""
|
|
if not os.path.isfile(CONF_PATH):
|
|
with open(CONF_PATH, 'w') as file_handle:
|
|
file_handle.write(CONF)
|
|
|
|
with open(SYSTEMD_SERVICE_PATH, 'w') as file_handle:
|
|
file_handle.write(SYSTEMD_SERVICE)
|
|
|
|
subprocess.check_call(['systemctl', 'daemon-reload'])
|
|
|
|
# Create infinoted group if needed.
|
|
try:
|
|
grp.getgrnam('infinoted')
|
|
except KeyError:
|
|
subprocess.run(['addgroup', '--system', 'infinoted'], check=True)
|
|
|
|
# Create infinoted user if needed.
|
|
try:
|
|
pwd.getpwnam('infinoted')
|
|
except KeyError:
|
|
subprocess.run([
|
|
'adduser', '--system', '--ingroup', 'infinoted', '--home',
|
|
DATA_DIR, '--gecos', 'Infinoted collaborative editing server',
|
|
'infinoted'
|
|
], check=True)
|
|
|
|
for directory in (DATA_DIR, KEY_DIR, SYNC_DIR):
|
|
if not os.path.exists(directory):
|
|
os.makedirs(directory, mode=0o750)
|
|
shutil.chown(directory, user='infinoted', group='infinoted')
|
|
|
|
if not os.path.exists(KEY_DIR + '/infinoted-cert.pem'):
|
|
old_umask = os.umask(0o027)
|
|
try:
|
|
# infinoted doesn't have a "create key and exit" mode. Run as
|
|
# daemon so we can stop after.
|
|
subprocess.run([
|
|
'infinoted', '--create-key', '--create-certificate',
|
|
'--daemonize'
|
|
], check=True)
|
|
_kill_daemon()
|
|
finally:
|
|
os.umask(old_umask)
|
|
|
|
# Always check the ownership of certificate files, in case setup
|
|
# failed previously.
|
|
shutil.chown(KEY_DIR + '/infinoted-cert.pem', user='infinoted',
|
|
group='infinoted')
|
|
shutil.chown(KEY_DIR + '/infinoted-key.pem', user='infinoted',
|
|
group='infinoted')
|
|
|
|
action_utils.service_enable('infinoted')
|
|
|
|
|
|
def main():
|
|
"""Parse arguments and perform all duties."""
|
|
arguments = parse_arguments()
|
|
|
|
subcommand = arguments.subcommand.replace('-', '_')
|
|
subcommand_method = globals()['subcommand_' + subcommand]
|
|
subcommand_method(arguments)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|