| .vscode | ||
| bin | ||
| caddy | ||
| data | ||
| database-lib | ||
| docker-compose | ||
| freedium-library | ||
| medium-parser | ||
| new-web | ||
| plausible/clickhouse | ||
| proxy-balancer | ||
| rl_string_helper | ||
| scripts | ||
| sitemap-generator | ||
| test_lab | ||
| tests | ||
| web | ||
| wgcf | ||
| .dockerignore | ||
| .env_template | ||
| .gitignore | ||
| Dockerfile | ||
| mypy.ini | ||
| README.md | ||
Freedium: Your paywall breakthrough for Medium!
Stack:
- Backend: Python 3.9+, Unicorn, FastAPI, Jinja2, Sentry
- Frontend: Tailwinds CSS v3
- Database: PostgreSQL, Dragonfly (Redis and Memcached compatible key-value database)
- Utils: Caddy, Docker, Docker Compose, Cloudflare WARP proxy (wgcf)
Local run:
There is two profiles:
min- without 2 Cluster of Cloudflare WARP proxy, HAProxy proxy balancer, Plausible, Grafana.prod- with all services for production.
For local development, we recommend to use min profile.
Requirements:
- Docker
- git
- Linux. Officially, we can't guarantee that Freedium will work on other OS.
To configure your Freedium instance, follow these steps:
-
Clone the repository:
git clone https://codeberg.org/Freedium-cfd/web/ ./freedium-web --depth 1 cd ./freedium-web -
Create and configure the environment file:
cp .env_template .envOpen the
.envfile and adjust the values as needed for your setup. -
(Optional) Set up the Docker network:
sudo docker network create caddy_freedium_net -
Change your hosts file:
sudo nano /etc/hostsAdd the following line:
127.0.0.1 freedium.local -
Start the Freedium services (
minprofile):sudo docker compose --profile min -f ./docker-compose/docker-compose.yml upStopping the services:
sudo docker compose --profile min -f ./docker-compose/docker-compose.yml down -
(Optional) Configure your reverse proxy (Caddy, Nginx, etc.) to use
freedium.localas a host.
If you use Dockerized reverse proxy, you can specify network caddy_freedium_net with external: true option in networks section of your reverse proxy container. Specify caddy_freedium hostname with port 80 (or 443) in your reverse proxy configuration.
And now you can access local instance of Freedium by opening browser and type https://freedium.local. There is would be a warning about insecure connection, because we use self-signed TLS certificate. Ignore it.
Architecture:
graph TB
subgraph "Main Application"
fw[freedium_web]
cdy[caddy_freedium]
end
subgraph "Database Layer"
rds[redis_service<br/>DragonFlyDB]
pg[(postgres_freedium<br/>PostgreSQL)]
pgadm[pgadmin4_freedium]
end
subgraph "Proxy Layer"
hpb[haproxy-proxy-balancer]
subgraph "WGCF Cluster 1"
wg1[wgcf1]
d1[dante_1]
wh1[wgcf1_healthcare_service]
end
subgraph "WGCF Cluster 2"
wg2[wgcf2]
d2[dante_2]
wh2[wgcf2_healthcare_service]
end
end
subgraph "Analytics"
pls[freedium_plausible]
pldb[(plausible_db)]
pledb[(plausible_events_db<br/>ClickHouse)]
end
subgraph "Utility"
ah[autoheal]
end
%% Dependencies
fw -->|depends_on| hpb
d1 -->|depends_on| wg1
d2 -->|depends_on| wg2
wg2 -->|depends_on| wg1
hpb -->|depends_on| wg1
hpb -->|depends_on| wg2
pls -->|depends_on| pldb
pls -->|depends_on| pledb
%% Network Connections
subgraph "Networks"
fn[freedium_net]
cn[caddy_net]
pn[plausible_net]
end
fw ---|freedium_net| fn
cdy ---|freedium_net & caddy_net| fn
rds ---|freedium_net| fn
pg ---|freedium_net| fn
pgadm ---|freedium_net| fn
hpb ---|freedium_net| fn
wg1 ---|freedium_net| fn
wg2 ---|freedium_net| fn
wh1 ---|freedium_net| fn
wh2 ---|freedium_net| fn
pls ---|all networks| fn
%% Port Exposures
cdy -->|":6752"| ext1[External Access]
fw -->|":7080"| ext2[External Access]
pgadm -->|":5433"| ext3[External Access]
classDef service fill:#2ecc71,stroke:#27ae60,color:white
classDef network fill:#3498db,stroke:#2980b9,color:white
classDef database fill:#e74c3c,stroke:#c0392b,color:white
classDef proxy fill:#f1c40f,stroke:#f39c12,color:black
classDef utility fill:#9b59b6,stroke:#8e44ad,color:white
classDef external fill:#95a5a6,stroke:#7f8c8d,color:white
class fw,cdy,pls service
class rds,pg,pldb,pledb database
class hpb,wg1,wg2,d1,d2 proxy
class ah,wh1,wh2 utility
class fn,cn,pn network
class ext1,ext2,ext3 external
TODO:
Integrate library notifiers - https://github.com/liiight/notifiersUse Graphana and Loki instead- Do not use 'shturman/dante' image, because it is does not have updates for a long time. (Probably) Use https://hub.docker.com/r/vimagick/dante/
Roadmap
- Speed up parser logic, port to Cython or rewrite to Golang
- Make parse Medium format directly to Markdown, not HTML, in order to make it more universal. This helps to generate RSS feeds, PDF, HTML. OR we need write separate parser for different formats, like PDF, Markdown, etc.
- Add more services than just a Medium
- Rewrite frontend to Svelte
- Move frontend to Cloudflare Pages
- Integrate Grafana/Prometheus to monitor our services
- Add more metrics to our services to have ability to monitor it
- Make able translate posts to different languages using translatepy library