Add support for config file

main
Micke Nordin 4 years ago
parent df7267af48
commit c70b900fe2

@ -15,9 +15,11 @@ RUN openssl req \
-extensions san \ -extensions san \
-config openssl.conf -config openssl.conf
FROM python:3 AS deploy-stage FROM python:3 AS deploy-stage
RUN pip install pyyaml
WORKDIR /app WORKDIR /app
COPY ./gmnd/__init__.py . COPY ./gmnd/__init__.py .
COPY ./content content COPY ./content content
COPY config.yml .
COPY --from=build-stage /app/certs certs COPY --from=build-stage /app/certs certs
EXPOSE 1965 EXPOSE 1965
CMD ["python", "__init__.py"] CMD ["python", "__init__.py", "--file", "config.yml" ]

@ -1,15 +1,19 @@
# gMNd # gMNd
gMNd is my gemini server, which is written in python. gMNd is my gemini server, which is written in python.
Currently it only serves static files. You can build and run it from the supplied Dockerfile if you so whish Currently it only serves static files. You can build and run it from the supplied Dockerfile if you so whish:
``` ```
docker build -t gmnd:latest . docker build -t gmnd:latest .
``` ```
By just running it, it will create self signed certs and serve example content from this repo By just running it, it will create self signed certs and serve example content from this repo:
``` ```
docker run -p 1965:1965 gmnd docker run -p 1965:1965 gmnd
``` ```
A slightly more interesting thing it can do is serve your own content, in this example from /tm/content on your host machine A slightly more interesting thing it can do is serve your own content, in this example from /tmp/content on your host machine:
``` ```
docker run --mount type=bind,source="/tmp/content,target=/app/content" -p 1965:1965 gmnd docker run --mount type=bind,source="/tmp/content,target=/app/content" -p 1965:1965 gmnd
``` ```
Or even supply your own certificates from the outside, in this example in /usr/local/certs:
```
docker run --mount type=bind,source="/tmp/content,target=/app/content" --mount type=bind,source="/usr/local/certs,target=/app/certs" -p 1965:1965 gmnd
```

@ -7,22 +7,48 @@ import sys
from socket import AF_INET, SHUT_RDWR, SO_REUSEADDR, SOCK_STREAM, SOL_SOCKET from socket import AF_INET, SHUT_RDWR, SO_REUSEADDR, SOCK_STREAM, SOL_SOCKET
from urllib.parse import urlparse from urllib.parse import urlparse
import yaml
class gMNd: class gMNd:
def __init__(self, options={}): def __init__(self, options={}):
self.allow_dir_list = options.get('allow_dir_list', False)
self.base_path = options.get('base_path', './content') self.base_path = options.get('base_path', './content')
self.logg_level = options.get('logg_level', logging.INFO) self.config_file = options.get('config_file', None)
self.listen_addr = options.get('listen_addr', '127.0.0.1') self.listen_addr = options.get('listen_addr', '127.0.0.1')
self.allow_dir_list = options.get('allow_dir_list', False)
self.listen_port = options.get('listen_port', 1965) self.listen_port = options.get('listen_port', 1965)
self.logg_level = options.get('logg_level', logging.INFO)
self.server_cert = options.get('server_cert', './certs/cert.pem') self.server_cert = options.get('server_cert', './certs/cert.pem')
self.server_key = options.get('server_key', './certs/cert.key') self.server_key = options.get('server_key', './certs/cert.key')
logging.basicConfig(stream=sys.stderr, level=self.logg_level) logging.basicConfig(stream=sys.stderr, level=self.logg_level)
if self.config_file:
if os.path.isfile(self.config_file):
self.read_config()
else:
logging.warning("Config file supplied, but it is not a file")
self.bindsocket = socket.socket() self.bindsocket = socket.socket()
self.bindsocket.bind((self.listen_addr, self.listen_port)) self.bindsocket.bind((self.listen_addr, self.listen_port))
self.bindsocket.listen(5) self.bindsocket.listen(5)
def read_config(self):
with open(self.config_file) as configfile:
config_dict = yaml.load(configfile, Loader=yaml.FullLoader)
if 'allow_dir_list' in config_dict:
self.allow_dir_list = config_dict['allow_dir_list']
if 'base_path' in config_dict:
self.base_path = config_dict['base_path']
if 'listen_addr' in config_dict:
self.listen_addr = config_dict['listen_addr']
if 'listen_port' in config_dict:
self.listen_port = config_dict['listen_port']
if 'logg_level' in config_dict:
self.logg_level = config_dict['logg_level']
if 'server_cert' in config_dict:
self.server_cert = config_dict['server_cert']
if 'server_key' in config_dict:
self.server_key = config_dict['server_key']
def run(self): def run(self):
while True: while True:
logging.debug("Waiting for client") logging.debug("Waiting for client")
@ -37,14 +63,14 @@ class gMNd:
conn.getpeercert())) conn.getpeercert()))
try: try:
request = conn.recv() request = conn.recv()
logging.debug(request) logging.debug("Full request: {}".format(request))
url = urlparse(request) url = urlparse(request)
scheme = url.scheme.decode() scheme = url.scheme.decode()
netloc = url.netloc.decode() netloc = url.netloc.decode()
path = url.path.decode().rstrip() path = url.path.decode().rstrip()
logging.debug(scheme) logging.debug("Scheme: {}".format(scheme))
logging.debug(netloc) logging.debug("Netloc: {}".format(netloc))
logging.debug(path) logging.debug("Path: {}".format(path))
header = get_header() header = get_header()
body = b"" body = b""
@ -52,8 +78,8 @@ class gMNd:
if not path.endswith(".gmi"): if not path.endswith(".gmi"):
header = get_header( header = get_header(
'20', '20',
mimetypes.guess_type( mimetypes.guess_type(self.base_path +
self.base_path + path)[0].encode()) path)[0].encode())
cfile = open(self.base_path + path) cfile = open(self.base_path + path)
body = cfile.read().encode() body = cfile.read().encode()
cfile.close() cfile.close()
@ -63,7 +89,7 @@ class gMNd:
'/index.gmi') '/index.gmi')
body = cfile.read().encode() body = cfile.read().encode()
cfile.close() cfile.close()
logging.debug(body) logging.debug("Body: {}".format(body))
elif os.path.isdir(self.base_path + elif os.path.isdir(self.base_path +
path) and self.allow_dir_list: path) and self.allow_dir_list:
body = self.get_dir_list(path) body = self.get_dir_list(path)
@ -111,8 +137,8 @@ def get_header(status='20', meta=b"text/gemini"):
if __name__ == "__main__": if __name__ == "__main__":
server = gMNd({ options = {}
'allow_dir_list': True, if (sys.argv[1] == "-f" or sys.argv[1] == "--file") and sys.argv[2]:
'listen_addr': '0.0.0.0' options['config_file'] = sys.argv[2]
}) server = gMNd(options)
server.run() server.run()

Loading…
Cancel
Save