fix Dockerfile and create a docker management script

This commit is contained in:
Izalia Mae 2022-04-12 04:13:14 -04:00
parent d322d41f07
commit 51984573da
7 changed files with 135 additions and 25 deletions

View file

@ -1,11 +1,28 @@
FROM python:3-alpine
WORKDIR /workdir
# install build deps for pycryptodome and other c-based python modules
RUN apk add alpine-sdk autoconf automake libtool gcc
ADD requirements.txt /workdir/
RUN pip3 install -r requirements.txt
# add env var to let the relay know it's in a container
ENV DOCKER_RUNNING=true
ADD . /workdir/
# setup various container properties
VOLUME ["/data"]
CMD ["python", "-m", "relay"]
EXPOSE 8080/tcp
WORKDIR /opt/activityrelay
VOLUME ["/workdir/data"]
# install and update important python modules
RUN pip3 install -U setuptools wheel pip
# only copy necessary files
COPY relay ./relay
COPY LICENSE .
COPY README.md .
COPY requirements.txt .
COPY setup.cfg .
COPY setup.py .
COPY .git ./.git
# install relay deps
RUN pip3 install -r requirements.txt

View file

@ -15,9 +15,9 @@ in this package as the `LICENSE` file.
You need at least Python 3.6 (latest version of 3.x recommended) to make use of this software.
It simply will not run on older Python versions.
Download the project and install with pip (`pip3 install .`).
Download the project and install with pip (`pip3 install -r requirements.txt`).
Run `activityrelay setup` and answer the prompts or copy `relay.yaml.example` to `relay.yaml`
Run `python3 -m relay setup` and answer the prompts or copy `relay.yaml.example` to `relay.yaml`
and edit it as appropriate:
$ cp relay.yaml.example relay.yaml
@ -25,7 +25,7 @@ and edit it as appropriate:
Finally, you can launch the relay:
$ activityrelay run
$ python3 -m relay run
It is suggested to run this under some sort of supervisor, such as runit, daemontools,
s6 or systemd. Configuration of the supervisor is not covered here, as it is different
@ -60,17 +60,12 @@ You can perform a few management tasks such as peering or depeering other relays
This will show the available management tasks:
$ activityrelay --help
$ python3 -m relay --help
When following remote relays, you should use the `/actor` endpoint as you would in
Pleroma and other LitePub-compliant software.
## Docker
You can run ActivityRelay with docker. Edit `relay.yaml` so that the database
location is set to `./data/relay.jsonld` and then build and run the docker
image :
$ docker volume create activityrelay-data
$ docker build -t activityrelay .
$ docker run -d -p 8080:8080 -v activityrelay-data:/workdir/data activityrelay
You can run ActivityRelay with docker via the docker management script: `docker.sh`.
Run it without arguments to see the list of commands.

66
docker.sh Executable file
View file

@ -0,0 +1,66 @@
#!/usr/bin/env bash
case $1 in
install)
docker build -f Dockerfile -t activityrelay . && \
docker volume create activityrelay-data && \
docker run -it -p 8080:8080 -v activityrelay-data:/data --name activityrelay activityrelay
;;
uninstall)
docker stop activityrelay && \
docker container rm activityrelay && \
docker volume rm activityrelay-data && \
docker image rm activityrelay
;;
start)
docker start activityrelay
;;
stop)
docker stop activityrelay
;;
manage)
shift
docker exec -it activityrelay python3 -m relay "$@"
;;
shell)
docker exec -it activityrelay bash
;;
rescue)
docker run -it --rm --entrypoint bash -v activityrelay-data:/data activityrelay
;;
edit)
if [ -z ${EDITOR} ]; then
echo "EDITOR environmental variable not set"
exit
fi
CONFIG="/tmp/relay-$(date +"%T").yaml"
docker cp activityrelay:/data/relay.yaml $CONFIG && \
$EDITOR $CONFIG && \
docker cp $CONFIG activityrelay:/data/relay.yaml && \
rm $CONFIG
;;
*)
COLS="%-22s %s\n"
echo "Valid commands:"
printf "$COLS" "- start" "Run the relay in the background"
printf "$COLS" "- stop" "Stop the relay"
printf "$COLS" "- manage <cmd> [args]" "Run a relay management command"
printf "$COLS" "- edit" "Edit the relay's config in \$EDITOR"
printf "$COLS" "- shell" "Drop into a bash shell on the running container"
printf "$COLS" "- rescue" "Drop into a bash shell on a temp container with the data volume mounted"
printf "$COLS" "- install" "Build the image, create a new container and volume, and run relay setup"
printf "$COLS" "- uninstall" "Delete the relay image, container, and volume"
;;
esac

View file

@ -60,11 +60,15 @@ class RelayConfig(DotDict):
}
def __init__(self, path):
self._path = Path(path).expanduser().resolve()
def __init__(self, path, is_docker):
if is_docker:
path = '/data/relay.yaml'
self._isdocker = is_docker
self._path = Path(path).expanduser()
super().__init__({
'db': f'{self._path.stem}.jsonld',
'db': str(self._path.parent.joinpath(f'{self._path.stem}.jsonld')),
'listen': '0.0.0.0',
'port': 8080,
'note': 'Make a note about your instance here.',
@ -81,6 +85,9 @@ class RelayConfig(DotDict):
def __setitem__(self, key, value):
if self._isdocker and key in ['db', 'listen', 'port']:
return
if key in ['blocked_instances', 'blocked_software', 'whitelist']:
assert isinstance(value, (list, set, tuple))
@ -234,7 +241,7 @@ class RelayConfig(DotDict):
self[key] = value
if self.host == 'example.com':
if self.host.endswith('example.com'):
return False
return True

View file

@ -3,6 +3,7 @@ import asyncio
import click
import json
import logging
import os
import platform
from aiohttp.web import AppRunner, TCPSite
@ -11,14 +12,15 @@ from cachetools import LRUCache
from . import app, misc, views
from .config import DotDict, RelayConfig
from .database import RelayDatabase
from .misc import follow_remote_actor, unfollow_remote_actor
from .misc import check_open_port, follow_remote_actor, unfollow_remote_actor
@click.group('cli', context_settings={'show_default': True}, invoke_without_command=True)
@click.option('--config', '-c', default='relay.yaml', help='path to the relay\'s config')
@click.pass_context
def cli(ctx, config):
app['config'] = RelayConfig(config)
app['is_docker'] = bool(os.environ.get('DOCKER_RUNNING'))
app['config'] = RelayConfig(config, app['is_docker'])
if not app['config'].load():
app['config'].save()
@ -33,7 +35,11 @@ def cli(ctx, config):
app['cache'][key] = LRUCache(app['config'][key])
if not ctx.invoked_subcommand:
relay_run.callback()
if app['config'].host.endswith('example.com'):
relay_setup.callback()
else:
relay_run.callback()
@cli.command('list')
@ -239,7 +245,7 @@ def relay_setup():
config.save()
if click.confirm('Relay all setup! Would you like to run it now?'):
if not app['is_docker'] and click.confirm('Relay all setup! Would you like to run it now?'):
relay_run.callback()
@ -247,7 +253,9 @@ def relay_setup():
def relay_run():
'Run the relay'
if app['config'].host.endswith('example.com'):
config = app['config']
if config.host.endswith('example.com'):
return click.echo('Relay is not set up. Please edit your relay config or run "activityrelay setup".')
vers_split = platform.python_version().split('.')
@ -262,6 +270,9 @@ def relay_run():
click.echo('Warning: PyCrypto is old and should be replaced with pycryptodome')
return click.echo(pip_command)
if not check_open_port(config.listen, config.port):
return click.echo(f'Error: A server is already running on port {config.port}')
# web pages
app.router.add_get('/', views.home)

View file

@ -2,6 +2,7 @@ import asyncio
import base64
import json
import logging
import socket
import traceback
from Crypto.Hash import SHA, SHA256, SHA512
@ -28,6 +29,18 @@ def build_signing_string(headers, used_headers):
return '\n'.join(map(lambda x: ': '.join([x.lower(), headers[x]]), used_headers))
def check_open_port(host, port):
if host == '0.0.0.0':
host = '127.0.0.1'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
return s.connect_ex((host , port)) != 0
except socket.error as e:
return False
def create_signature_header(headers):
headers = {k.lower(): v for k, v in headers.items()}
used_headers = headers.keys()

1
requirements.txt Normal file
View file

@ -0,0 +1 @@
.