initial commit

This commit is contained in:
Philip Henning 2025-09-05 10:39:25 +02:00
commit eb2ec18ad9
6 changed files with 357 additions and 0 deletions

83
.gitignore vendored Normal file
View file

@ -0,0 +1,83 @@
.env
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# Metadata left by Dolphin file manager, which comes with KDE Plasma
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# Log files created by default by the nohup command
nohup.out
# General
.DS_Store
__MACOSX/
.AppleDouble
.LSOverride
Icon[
]
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
!*.code-workspace
# Built Visual Studio Code Extensions
*.vsix

0
README.md Normal file
View file

View file

@ -0,0 +1,140 @@
# customize to your needs
import re
import os
# You must insert your own random value here
# SECURITY WARNING: keep the secret key used in production secret!
# see <https://docs.djangoproject.com/en/dev/howto/deployment/checklist/#secret-key>
SECRET_KEY = os.environ.get('BITPOLL_SECRET_KEY', '...')
# generate via: ./manage.py generate_encryption_key
FIELD_ENCRYPTION_KEY = os.environ.get('BITPOLL_FIELD_ENCRYPTION_KEY', 'this+is+an+example+key+please+generate+one+=')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
# The domain name of the site
ALLOWED_HOSTS = ['poll.s1q.dev']
## If Bitpoll is served via HTTPS enable the next two options
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# The root dir bitpoll appears to be in from the web, as configured in the webserver
URL_PREFIX = ''
#Add additionall installed apps here
## Example for installed raven (Sentry instrumentation)
#INSTALLED_APPS_LOCAL = [
# 'raven.contrib.django.raven_compat',
# ]
INSTALLED_APPS_LOCAL = []
# To use OpenId:
#INSTALLED_APPS_LOCAL.append('simple_openid_connect.integrations.django')
#OPENID_ENABLED = True
#OPENID_ISSUER = "https://identity.mafiasi.de/realms/mafiasi"
#OPENID_API_BASE = "https://identity.mafiasi.de/admin/realms/mafiasi"
#OPENID_CLIENT_ID = "..."
#OPENID_CLIENT_SECRET = "..."
#OPENID_BASE_URI = "..."
#OPENID_SCOPE = "openid profile email"
#OPENID_USER_MAPPER = 'bitpoll.base.openid.BitpollUserMapper'
#OPENID_ADMIN_GROUPS = re.compile('admins|superusers')
#LOGIN_URL = "simple_openid_connect_django:login"
#LOGOUT_REDIRECT_URL = "index"
MIDDLEWARE_LOCAL = [
# "simple_openid_connect.integrations.django.middleware.TokenVerificationMiddleware",
]
# Compress the JS and CSS files, for more Options see https://django-pipeline.readthedocs.io/en/latest/compressors.html
# the Compressor have to be installed in the system
PIPELINE_LOCAL = {}
#PIPELINE_LOCAL['JS_COMPRESSOR'] = 'pipeline.compressors.uglifyjs.UglifyJSCompressor'
#PIPELINE_LOCAL['CSS_COMPRESSOR'] = 'pipeline.compressors.cssmin.CSSMinCompressor'
#PIPELINE_ENABLED = True
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
## https://docs.djangoproject.com/en/1.9/ref/settings/#databases
#DATABASES = {
# 'default': {+
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
#}
DATABASES = {
"default": {+
"ENGINE": "django.db.backends.postgresql",
"NAME": "bitpoll",
"USER": "bitpoll",
"PASSWORD": os.environ.get('BITPOLL_DB_PASSWORD', 'password'),
"HOST": "db",
"PORT": 5432,
"CONN_MAX_AGE": 60,
}
}
## Customize your instance
SITE_NAME = 's1q poll'
BASE_URL = 'https://poll.s1q.dev'
## Url to the Base Homepage and Text on the Link, leave empty to not use this option
#HOME_URL = "https://example.com"
#HOME_URL_NAME = "Dashboard"
## Test mail functionality by printing mails to console:
## EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
## if the imprint URL is not empty use it as an link to the imprint, else use IMPRINT_TEXT
#IMPRINT_URL = ""
#IMPRINT_TEXT = """
#<h1>ImpressuXm</h1>
#<p>Text goes here</p>
#"""
#LOCALE_PATHS = (os.path.join(ROOT_DIR, 'locale'), )
LANGUAGES = (
('de', 'Deutsch'),
('en', 'English'),
#('fr', 'Français'),
#('it', 'Italiano'),
)
REGISTER_ENABLED = True
GROUP_MANAGEMENT = REGISTER_ENABLED
## Use ldap login
#import ldap
#from django_auth_ldap.config import LDAPSearch
#
#AUTHENTICATION_BACKENDS = (
# 'django_auth_ldap.backend.LDAPBackend',
# 'django.contrib.auth.backends.ModelBackend',
# )
#
#AUTH_LDAP_SERVER_URI = "ldap_host"
#AUTH_LDAP_BIND_DN = "ldap_bind_dn"
#AUTH_LDAP_BIND_PASSWORD = "ldap_bind_pw"
#AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=People,dc=mafiasi,dc=de",
# ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
#AUTH_LDAP_ALWAYS_UPDATE_USER = True
#
#from django_auth_ldap.config import LDAPSearch, PosixGroupType
#
#AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=groups,dc=mafiasi,dc=de",
# ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)"
# )
#AUTH_LDAP_GROUP_TYPE = PosixGroupType()
##AUTH_LDAP_FIND_GROUP_PERMS = True
#AUTH_LDAP_MIRROR_GROUPS = True
#
#AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn", "email": "mail"}
#
#AUTH_LDAP_USER_FLAGS_BY_GROUP = {
# "is_staff": ["cn=Editoren,ou=groups,dc=mafiasi,dc=de",
# "cn=Server-AG,ou=groups,dc=mafiasi,dc=de"],
# "is_superuser": "cn=Server-AG,ou=groups,dc=mafiasi,dc=de"
#}

View file

@ -0,0 +1,19 @@
server {
listen 8080;
server_name default_server;
root /var/www;
location / {
include uwsgi_params;
uwsgi_pass bitpoll:3008;
}
location /static {
expires 14d;
alias /opt/static;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}

100
docker-compose.yml Normal file
View file

@ -0,0 +1,100 @@
---
services:
nginx:
image: ghcr.io/nginx/nginx-unprivileged:${NGINX_TAG:?NGINX_TAG is not configured}
restart: unless-stopped
depends_on:
- bitpoll
read_only: true
volumes:
# - /etc/localtime:/etc/localtime:ro
# - /etc/timezone:/etc/timezone:ro
- ./data/config/nginx-templates:/etc/nginx/templates:ro
- static:/var/www
tmpfs:
- /etc/nginx/conf.d:uid=101,gid=101
- /tmp
- /var/cache/nginx
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
networks:
- appnet
- dokploy-network
labels:
- "traefik.enable=true"
- "traefik.docker.network=dokploy-network"
- "traefik.http.services.bitpoll-nginx.loadbalancer.server.port=8080" # set port the container listenes to
- "traefik.http.services.bitpoll-nginx.loadbalancer.server.scheme=http"
- "traefik.http.routers.bitpoll-nginx-web.rule=Host(`${PUBLIC_DOMAIN}`)"
- "traefik.http.routers.bitpoll-nginx-web.service=bitpoll-nginx@docker"
- "traefik.http.routers.bitpoll-nginx-web.entrypoints=web"
- "traefik.http.routers.bitpoll-nginx-web.middlewares=redirect-to-https@file"
- "traefik.http.routers.bitpoll-nginx-websecure.rule=Host(`${PUBLIC_DOMAIN}`)" # change hostname!
- "traefik.http.routers.bitpoll-nginx-websecure.service=bitpoll-nginx@docker"
- "traefik.http.routers.bitpoll-nginx-websecure.entrypoints=websecure"
- "traefik.http.routers.bitpoll-nginx-websecure.tls=true"
- "traefik.http.routers.bitpoll-nginx-websecure.tls.options=modern@file"
- "traefik.http.routers.bitpoll-nginx-websecure.tls.certresolver=hetzner"
- "traefik.http.routers.bitpoll-nginx-websecure.tls.domains[0].main=${TLS_DOMAIN}"
- "traefik.http.routers.bitpoll-nginx-websecure.middlewares=secHeaders@file, hsts-header@file"
bitpoll:
image: ghcr.io/fsinfuhh/bitpoll:${BITPOLL_TAG:?BITPOLL_TAG is not configured}
build:
dockerfile: Dockerfile
context: ./src
restart: unless-stopped
depends_on:
postgresql:
condition: service_healthy
environment:
BITPOLL_SECRET_KEY: ${BITPOLL_SECRET_KEY?:BITPOLL_SECRET_KEY is required!}
BITPOLL_FIELD_ENCRYPTION_KEY: ${BITPOLL_FIELD_ENCRYPTION_KEY?:BITPOLL_FIELD_ENCRYPTION_KEY is required!}
BITPOLL_DB_PASSWORD: ${BITPOLL_DB_PASSWORD?:BITPOLL_DB_PASSWORD is required!}
networks:
- appnet
volumes:
# - /etc/localtime:/etc/localtime:ro
# - /etc/timezone:/etc/timezone:ro
- static:/opt/static
- ./data/config/bitpoll:/opt/config
- log:/opt/log
db:
image: postgres:${POSTGRES_TAG:?POSTGRES_TAG is not configured}
restart: unless-stopped
environment:
POSTGRES_USER: bitpoll
POSTGRES_DB: bitpoll
POSTGRES_PASSWORD: ${BITPOLL_DB_PASSWORD?:BITPOLL_DB_PASSWORD is required!}
healthcheck:
interval: 30s
retries: 5
start_period: 20s
test:
- CMD-SHELL
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
timeout: 5s
networks:
- appnet
volumes:
- db:/var/lib/postgresql/data:rw
volumes:
static:
driver: local
log:
driver: local
db:
driver: local
networks:
appnet:
dokploy-network:
# external: true

15
template.env Normal file
View file

@ -0,0 +1,15 @@
# SETTINGS from env.template
# Misc configuration
COMPOSE_PROJECT_NAME=poll-s1q-dev
PUBLIC_DOMAIN=poll.s1q.dev
TLS_DOMAIN=*.s1q.dev
# Container Tags
NGINX_TAG=1.29.1
BITPOLL_TAG=latest
POSTGRES_TAG=17.6
# Secrets
# BITPOLL_SECRET_KEY="" # generate via: openssl rand -base64 128 | tr -d '\n'
# BITPOLL_FIELD_ENCRYPTION_KEY="" # generate via: ./manage.py generate_encryption_key / docker run --rm --volume ./data/config/bitpoll:/opt/config --entrypoint ./manage.py ghcr.io/fsinfuhh/bitpoll:latest generate_encryption_key
# BITPOLL_DB_PASSWORD="password" # generate via: openssl rand -base64 128 | tr -d '\n'