Add support for config file
This commit is contained in:
parent
df7267af48
commit
c70b900fe2
3 changed files with 50 additions and 18 deletions
|
@ -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" ]
|
||||||
|
|
10
README.md
10
README.md
|
@ -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.base_path = options.get('base_path', './content')
|
|
||||||
self.logg_level = options.get('logg_level', logging.INFO)
|
|
||||||
self.listen_addr = options.get('listen_addr', '127.0.0.1')
|
|
||||||
self.allow_dir_list = options.get('allow_dir_list', False)
|
self.allow_dir_list = options.get('allow_dir_list', False)
|
||||||
|
self.base_path = options.get('base_path', './content')
|
||||||
|
self.config_file = options.get('config_file', None)
|
||||||
|
self.listen_addr = options.get('listen_addr', '127.0.0.1')
|
||||||
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…
Add table
Reference in a new issue