You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
Trent Larson 72653abaf5 fix DB path and add instructions for docker deployment 10 months ago
.gitignore WIP: building up VAPID and subscription 12 months ago
Dockerfile OOP and documented 12 months ago
README.md fix DB path and add instructions for docker deployment 10 months ago
app.py fix DB path and add instructions for docker deployment 10 months ago
b64.py Add a pause before sending to the gateway 12 months ago
build.sh WIP: building up VAPID and subscription 12 months ago
init_db.py Somewhat stable VAPID generation 12 months ago
models.py Somewhat stable VAPID generation 12 months ago
requirements.txt OOP and documented 12 months ago
webpush.py Add a pause before sending to the gateway 12 months ago

README.md

py-push-server

Docker Build & Deploy

export PUSH_SERVER_VERSION=0.1

# also in build.sh
docker build --tag py-push-server:amd-$PUSH_SERVER_VERSION --platform linux/amd64 .

docker save -o ~/dl/py-push-server-amd-$PUSH_SERVER_VERSION.tar py-push-server:amd-$PUSH_SERVER_VERSION

bzip2 ~/dl/py-push-server-amd-$PUSH_SERVER_VERSION.tar

... and then on the server after transferring that file:

export PUSH_SERVER_VERSION=0.1

bzip2 -d py-push-server-amd-$PUSH_SERVER_VERSION.tar.bz2

sudo docker load -i py-push-server-amd-$PUSH_SERVER_VERSION.tar

sudo docker run -d -p 8900:3000 -v ~/py-push-server-db:/app/instance/data --name py-push-server-$PUSH_SERVER_VERSION py-push-server:amd-$PUSH_SERVER_VERSION

Docker Compose & HAProxy Setup

On first run you need to:

docker network create phoenix-network

HAProxy setup

... in docker-compose.yml ...

  default-backend:
    container_name: 'default-backend'
    image: nginx:1.22.0-alpine
    volumes:
      - /docker-volumes/haproxy-config/core/nginx/html:/usr/share/nginx/html
    restart: always
    networks:
      - phoenix-network

  rsyslog:
    container_name: 'rsyslog'
    hostname: 'rsyslog'
    image: alpine-rsyslog
    build:
      context: ./alpine-rsyslog
    volumes:
      - $PWD/haproxy-config/core/haproxy.conf:/etc/rsyslog.d/haproxy.conf
      - $PWD/haproxy-config/log:/var/log
      - $PWD/haproxy-config/spool:/var/spool
      - $PWD/rsyslog/rsyslog.conf:/etc/rsyslog.conf
    ports:
      - '127.0.0.1:514:514'
    networks:
      - phoenix-network


  haproxy:
    container_name: 'haproxy'
    hostname: 'haproxy'
    image: haproxytech/haproxy-alpine:latest
    ports:
      - 443:443
      - 80:80
    depends_on:
      - default-backend
      - rsyslog
    volumes:
      - $PWD/haproxy-config/log:/var/log
      - $PWD/haproxy-config/certs:/usr/local/etc/haproxy/certs:ro
      - $PWD/haproxy-config/core:/usr/local/etc/haproxy/core:ro
      - $PWD/haproxy-config/maps:/usr/local/etc/haproxy/maps:ro
      - $PWD/haproxy-config/sites:/usr/local/etc/haproxy/sites:ro
    command: "haproxy -f /usr/local/etc/haproxy/core/haproxy.cfg -f /usr/local/etc/haproxy/sites/"
    networks:
      - phoenix-network

in haproxy-config/core/haproxy.conf:

$UDPServerAddress 127.0.0.1
$UDPServerRun 514
local0.*    /var/log/haproxy.log
& ~

in haproxy-config/core/haproxy.cfg:

global
  tune.ssl.default-dh-param 2048
  log rsyslog:514 local0
  maxconn 4096

defaults
  option httplog
  option forwardfor except 127.0.0.1
  option forwardfor header X-Real-IP
  option http-no-delay
  log global
  mode http

  retries 10
  option  redispatch
  timeout connect 4000
  timeout client  600000
  timeout server  600000
  timeout queue 10s

frontend default_frontend
  mode http

  bind *:80
  bind *:443 ssl crt /usr/local/etc/haproxy/certs alpn h2,http/1.1

# redirect non-www

  # http-request redirect prefix https://%[hdr(Host),regsub(^www\.,,i)] code 301 if { hdr_beg(host) -i www. }

# Make a rule that the server cannot be directly accessed by IP address

  acl   has_domain hdr(Host),map_str(/usr/local/etc/haproxy/maps/domains.map) -m found
  http-request deny if !has_domain

# ACME challenge rule?

  acl letsencrypt-acl path_beg /.well-known/acme-challenge/
  redirect code 301 scheme https if !{ ssl_fc && letsencrypt-acl }
  compression algo gzip
  compression type text/css text/html text/javascript application/javascript text/plain text/xml application/json image/svg+xml
  acl is_content_type_html res.hdr(Content-Type) -i text/html
  http-response set-header Content-Type text/html;\ charset=UTF-8 if is_content_type_html
  http-response set-header Cache-Control no-cache,\ max-age=31536000
  http-response set-header Expires %[date(3600),http_date]
  http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
  http-response set-header X-XSS-Protection "1; mode=block"
  http-response set-header X-Content-Type-Options "nosniff"
  http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
  use_backend %[base,lower,regsub(^www\.,,i),map_beg(/usr/local/etc/haproxy/maps/sites.map,default_backend)]


listen stats
  bind *:9999
  mode http
  log global
  stats enable
  stats realm Haproxy\ Statistics
  stats uri /haproxy_stats
  stats hide-version


backend haproxy_stats_backend
  http-request auth realm haproxy-stats unless { http_auth_group(basic-auth-list) is-haproxy-stats }
  mode http
  compression algo gzip
  compression offload
  server server_nginx localhost:9999


userlist basic-auth-list
  group is-guest
  group is-haproxy-stats

  user guest password $5$N7CpS0mo$FyJtlwQOwzAi5HnCISumyBKWyPu6DhBO7eGzUUyWoJ7 groups is-guest

... in haproxy-config/sites/web-push.anomalistlabs.com.cfg ...

define an HAProxy backend and map it to the Docker host and port NOTE: this also turned off CORS origin rule

backend web_push_backend
  mode http
  compression algo gzip
  compression offload
  http-response set-header Access-Control-Allow-Origin "*"
  server server_nginx endorser-push-server:3000

... in haproxy-config/maps/domains.map ...

add a domain that will be used as a base

timesafari.anomalistlabs.com

... in haproxy-config/maps/sites.map ...

map the /web-push path to the web_push_backend NOTE: timesafari-pwa.anomalistlabs.com PWA sits on the root

timesafari-pwa.anomalistlabs.com/web-push/ web_push_backend

The rest ..

docker-compose up -d should just work :-)

Run the server outside Docker

Run the app:

sh <(curl https://pkgx.sh) +python.org +virtualenv.pypa.io sh

source venv/bin/activate

python app.py

# See Troubleshooting below if that doesn't work out of the box.

Run a test:

python webpush.py

Run haproxy (on a Mac):

  • Create "haproxy-config" directory for those files above, eg. /usr/local/etc/haproxy

  • Comment out the log rsyslog and bind *:443 lines in /usr/local/etc/haproxy/haproxy.cfg and then run:

haproxy -f /usr/local/etc/haproxy/haproxy.cfg

Troubleshooting

  • If you get "unable to open database file", you can edit the app.py line with SQLALCHEMY_DATABASE_URI and add sqlite:////... with the full path to the data/webpush.db file. (Why does the relative path of sqlite:///... not work for a relative path?)