Skip to content

hilf-mir.berlin is a web app for finding psychological and health related facilities in Berlin

License

Notifications You must be signed in to change notification settings

technologiestiftung/hilf-mir.berlin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

HILF-MIR Berlin

This repo hosts the code for the hilf-mir.berlin - a website for finding psychological and health-related facilities in Berlin.

Tech stack

The project is built using the React framework Next.js and TypeScript. The data of the facilities is stored in a self-hosted Grist instance. The frontend is deployed to Vercel and the backend is currently running on one of our own servers. See the section grist for a working example of the backend. The map is provided by maptiler.com

Setup

  • Copy .env.example to .env and fill in the required environment variables as per .env.example to connect to your Grist instance.
  • Install your dependencies via npm ci

Development

  • Start your grist instance
  • Create the tables. You can find an example sqlite database in ./docs/example.db with test data and the right rows.
  • Install dependencies via npm ci
  • Create a file .env.development.local and/or .env and fill it according to .env.example. The environment variables will connect to your development Grist instance.
  • Create fake data in your grist instance for development npx ts-node src/scripts/createFakeGristData.ts
  • Create your local cache. npm run downloadCacheData (will create json from your records under ./data/)
  • Run npm run dev to get a development server running at http://localhost:3000

If you want to start the app with the production table data, please change the values of .env.development.local to point to the production table.

Grist

Here is a working example of a docker-compose.yml to run Grist. Note that we are running this on a single node docker swarm. You might need to adjust this. Since grist has no auth built in, we use authentik (see below) for authentication. See this guide hon how to connect both.

version: "3.9"
services:
  grist:
    # even though it is bad practice to use the latest tag, we want the latest state. Last tag v0.7.9 is 4 month old. There has been so many changes since then.
    # Other possibility would be to pull latest and rename the tag to mach some versioning we can use.
    image: gristlabs/grist:latest
    restart: always
    # currently not needed with pynbox
    # once gvisor is available in grist-core we can use it
    # runtime: runsc
    ports:
      - published: 8080
        target: 80
        mode: host
    volumes:
      - grist:/persist
      - /path/to/your/custom.css:/grist/static/custom.css
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [ node.role == manager ]
    environment:

      DEBUG: "1"
      PORT: 80
      APP_DOC_URL: https://$GRIST_DOMAIN
      APP_HOME_URL: https://$GRIST_DOMAIN
        # GRIST_SINGLE_ORG: docs
      GRIST_ORG_IN_PATH: $GRIST_ORG_IN_PATH
      GRIST_DOMAIN: $GRIST_DOMAIN
      # GRIST_HOST: $GRIST_DOMAIN
      # GRIST_DEFAULT_EMAIL: $GRIST_DEFAULT_EMAIL
      GRIST_EXPERIMENTAL_PLUGINS: $GRIST_EXPERIMENTAL_PLUGINS
      GRIST_SANDBOX_FLAVOR: $GRIST_SANDBOX_FLAVOR
      GRIST_SESSION_SECRET: $GRIST_SESSION_SECRET
      APP_STATIC_INCLUDE_CUSTOM_CSS: $APP_STATIC_INCLUDE_CUSTOM_CSS

      GRIST_SAML_IDP_CERTS: $GRIST_SAML_IDP_CERTS
      GRIST_SAML_SP_KEY: $GRIST_SAML_SP_KEY
      GRIST_SAML_SP_CERT: $GRIST_SAML_SP_CERT
      GRIST_SAML_IDP_LOGIN: $GRIST_SAML_IDP_LOGIN
      GRIST_SAML_IDP_LOGOUT: $GRIST_SAML_IDP_LOGOUT
      GRIST_HIDE_UI_ELEMENTS: helpCenter,billing,templates
      PYTHON_VERSION: $PYTHON_VERSION
      PYTHON_VERSION_ON_CREATION: $PYTHON_VERSION_ON_CREATION
      GRIST_FORCE_LOGIN: $GRIST_FORCE_LOGIN
      GRIST_SAML_IDP_UNENCRYPTED: $GRIST_SAML_IDP_UNENCRYPTED
      GRIST_SAML_SP_HOST: https://$GRIST_DOMAIN
      PIPE_MODE: $PIPE_MODE
      ALLOWED_WEBHOOK_DOMAINS: $ALLOWED_WEBHOOK_DOMAINS
volumes:
  grist:

Here is an example .env for you to use:

GRIST_DOMAIN=
GRIST_SESSION_SECRET=
GRIST_SANDBOX_FLAVOR=
GRIST_ORG_IN_PATH=
APP_DOC_URL=
APP_HOME_URL=
PYTHON_VERSION=
PYTHON_VERSION_ON_CREATION=
GRIST_SAML_IDP_LOGIN=
GRIST_SAML_IDP_LOGOUT=
GRIST_SAML_IDP_CERTS=
GRIST_SAML_SP_KEY=
GRIST_SAML_SP_CERT=
GRIST_EXPERIMENTAL_PLUGINS=
GRIST_HIDE_UI_ELEMENTS=
GRIST_FORCE_LOGIN=
GRIST_SAML_IDP_UNENCRYPTED=
GRIST_SAML_SP_HOST=
PORT=

Authentik

Here is our authentik docker-compose.yml configuration.

version: '3.4'

services:
  postgresql:
    image: docker.io/library/postgres:12-alpine
    restart: unless-stopped
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"
        ]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=${PG_PASS:?database password required}
      - POSTGRES_USER=${PG_USER:-authentik}
      - POSTGRES_DB=${PG_DB:-authentik}
    # env_file:
    #   - .env
  redis:
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    image: docker.io/library/redis:alpine
    command: --save 60 1 --loglevel warning
    restart: unless-stopped
    healthcheck:
      test: [ "CMD-SHELL", "redis-cli ping | grep PONG" ]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - redis:/data
  server:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.9.0}
    restart: unless-stopped
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    command: server
    environment:

      AUTHENTIK_SECRET_KEY: $AUTHENTIK_SECRET_KEY
      AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
      # ----- email
      # SMTP Host Emails are sent to
      AUTHENTIK_EMAIL__HOST: $AUTHENTIK_EMAIL__HOST
      AUTHENTIK_EMAIL__PORT: $AUTHENTIK_EMAIL__PORT
      # Optionally authenticate (don't add quotation marks to you password)
      AUTHENTIK_EMAIL__USERNAME: $AUTHENTIK_EMAIL__USERNAME
      AUTHENTIK_EMAIL__PASSWORD: $AUTHENTIK_EMAIL__PASSWORD
      # Use StartTLS
      AUTHENTIK_EMAIL__USE_TLS: $AUTHENTIK_EMAIL__USE_TLS
      # Use SSL
      AUTHENTIK_EMAIL__USE_SSL: $AUTHENTIK_EMAIL__USE_SSL
      AUTHENTIK_EMAIL__TIMEOUT: 10
      # Email address authentik will send from, should have a correct @domain
      AUTHENTIK_EMAIL__FROM: $AUTHENTIK_EMAIL__FROM

      GEOIPUPDATE_ACCOUNT_ID: $GEOIPUPDATE_ACCOUNT_ID
      GEOIPUPDATE_LICENSE_KEY: $GEOIPUPDATE_LICENSE_KEY
      AUTHENTIK_AUTHENTIK__GEOIP: /geoip/GeoLite2-City.mmdb

      AUTHENTIK_PORT_HTTP: 9004
      AUTHENTIK_PORT_HTTPS: 9444
      AUTHENTIK_TAG: 2022.9.0
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
      AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      # AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
    volumes:
      - media:/media
      - custom-templates:/templates
      - geoip:/geoip
    # env_file:
    #   - .env
    ports:
      - published: 9004
        target: 9000

        mode: host
      - published: 9444
        target: 9443

        mode: host
      # - "0.0.0.0:${AUTHENTIK_PORT_HTTP:-9004}:9000"
      # - "0.0.0.0:${AUTHENTIK_PORT_HTTPS:-9444}:9443"
  worker:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.9.0}
    restart: unless-stopped
    command: worker
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    environment:
      AUTHENTIK_SECRET_KEY: $AUTHENTIK_SECRET_KEY
      AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
      # ----- email
      # SMTP Host Emails are sent to
      AUTHENTIK_EMAIL__HOST: $AUTHENTIK_EMAIL__HOST
      AUTHENTIK_EMAIL__PORT: $AUTHENTIK_EMAIL__PORT
      # Optionally authenticate (don't add quotation marks to you password)
      AUTHENTIK_EMAIL__USERNAME: $AUTHENTIK_EMAIL__USERNAME
      AUTHENTIK_EMAIL__PASSWORD: $AUTHENTIK_EMAIL__PASSWORD
      # Use StartTLS
      AUTHENTIK_EMAIL__USE_TLS: $AUTHENTIK_EMAIL__USE_TLS
      # Use SSL
      AUTHENTIK_EMAIL__USE_SSL: $AUTHENTIK_EMAIL__USE_SSL
      AUTHENTIK_EMAIL__TIMEOUT: ${AUTHENTIK_EMAIL__TIMEOUT:-10}
      # Email address authentik will send from, should have a correct @domain
      AUTHENTIK_EMAIL__FROM: $AUTHENTIK_EMAIL__FROM

      GEOIPUPDATE_ACCOUNT_ID: $GEOIPUPDATE_ACCOUNT_ID
      GEOIPUPDATE_LICENSE_KEY: $GEOIPUPDATE_LICENSE_KEY
      AUTHENTIK_AUTHENTIK__GEOIP: /geoip/GeoLite2-City.mmdb

      AUTHENTIK_PORT_HTTP: 9004
      AUTHENTIK_PORT_HTTPS: 9444
      AUTHENTIK_TAG: 2022.9.0
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
      AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      # AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
      # This is optional, and can be removed. If you remove this, the following will happen
      # - The permissions for the /media folders aren't fixed, so make sure they are 1000:1000
      # - The docker socket can't be accessed anymore
    user: root
    volumes:
      - media:/media
      - certs:/certs
      - /var/run/docker.sock:/var/run/docker.sock
      - custom-templates:/templates
      - geoip:/geoip
    # env_file:
    #   - .env
  geoipupdate:
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    image: "maxmindinc/geoipupdate:latest"
    volumes:
      - "geoip:/usr/share/GeoIP"
    environment:
      GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
      GEOIPUPDATE_FREQUENCY: "8"
      GEOIPUPDATE_ACCOUNT_ID: $GEOIPUPDATE_ACCOUNT_ID
      GEOIPUPDATE_LICENSE_KEY: $GEOIPUPDATE_LICENSE_KEY
    # env_file:
    #   - .env

volumes:
  database:
    driver: local
  redis:
    driver: local
  geoip:
    driver: local
  media:
    driver: local
  certs:
    driver: local
  custom-templates:
    driver: local

And the .env for authentik.

PG_PASS=
AUTHENTIK_SECRET_KEY=
AUTHENTIK_ERROR_REPORTING__ENABLED=

# ----- email

# SMTP Host Emails are sent to
AUTHENTIK_EMAIL__HOST=
AUTHENTIK_EMAIL__PORT=
# Optionally authenticate (don't add quotation marks to you password)
AUTHENTIK_EMAIL__USERNAME=
AUTHENTIK_EMAIL__PASSWORD=
# Use StartTLS
AUTHENTIK_EMAIL__USE_TLS=
# Use SSL
AUTHENTIK_EMAIL__USE_SSL=
AUTHENTIK_EMAIL__TIMEOUT=
# Email address authentik will send from, should have a correct @domain
AUTHENTIK_EMAIL__FROM=

GEOIPUPDATE_ACCOUNT_ID=
GEOIPUPDATE_LICENSE_KEY=
AUTHENTIK_AUTHENTIK__GEOIP=

AUTHENTIK_PORT_HTTP=
AUTHENTIK_PORT_HTTPS=
AUTHENTIK_TAG= 

Contributors

Thanks goes to these wonderful people (emoji key):

Dennis Ostendorf
Dennis Ostendorf

πŸ’» 🎨 πŸ“–
Lucas Vogel
Lucas Vogel

πŸ’» 🎨 πŸ“–
Fabian MorΓ³n Zirfas
Fabian MorΓ³n Zirfas

πŸ’» πŸ”£ πŸš‡
Ingo Hinterding
Ingo Hinterding

πŸ–‹ πŸ‘€ πŸ§‘β€πŸ«

This project follows the all-contributors specification. Contributions of any kind welcome!

Credits



A project by:

Supported by:

About

hilf-mir.berlin is a web app for finding psychological and health related facilities in Berlin

Topics

Resources

License

Stars

Watchers

Forks