Self-Hosted: Public Gateway
This article applies to: Self-Hosted
The pglombardo/pwpush-public-gateway container is a feature-limited version of the full pglombardo/pwpush container, designed to be hosted publicly and only deliver pushes to end users while keeping your internal infrastructure secure.
Overview
The public gateway container implements feature segmentation - a security strategy that reduces the attack surface by limiting functionality to only what’s needed for push delivery. This allows you to:
- Host publicly: Deploy the gateway container in a public-facing environment (cloud, DMZ, etc.)
- Keep internal: Run the full application container internally for your team
- Share database: Both containers connect to the same database
- Reduce risk: Limit what attackers can access if the public gateway is compromised
Use Cases
The public gateway is ideal for organizations that:
- Need to share pushes with external users (customers, partners, vendors)
- Want to isolate public-facing infrastructure from internal systems
- Require enhanced security through feature segmentation
- Need to scale public push delivery independently from internal operations
What’s Included vs Excluded
✅ Included (Public Gateway can do):
- View push contents (passwords, text, URLs, files)
- Access passphrase-protected pushes
- Delete/expire pushes (if enabled)
- Health check endpoint (
/up)
❌ Excluded (Public Gateway cannot do):
- Create new pushes
- User login and registration
- Administration dashboard (
/admin) - API endpoints
- File uploads
- Push management features
- Configuration changes
Note: The public gateway returns a 404 error for the root path (/) and other non-push routes. Users must access pushes via their secret URLs (e.g., https://gateway.example.com/p/abc123).
Benefits
- Improved Security: By hosting the public-facing push gateway in a separate container, you reduce the attack surface of your internal infrastructure. Even if the public gateway is compromised, attackers cannot:
- Create new pushes
- Access the admin dashboard
- Use the API
- Register new users
- Modify application configuration
-
Network Segmentation: Isolate public-facing components from internal systems, making it more difficult for attackers to move laterally into your internal network.
-
Flexibility: The public gateway can be hosted in a public cloud, on-premises DMZ, or hybrid environment, giving you deployment flexibility.
-
Scalability: Scale the public gateway independently to handle increased external traffic without affecting internal system performance.
- Compliance: Helps meet security requirements for separating public and internal infrastructure.
Security Considerations
The pglombardo/pwpush-public-gateway container employs feature segmentation, a well-established security strategy that reduces the attack surface by dividing a system into isolated segments. This approach is commonly used in networking, services, and applications to prevent unauthorized access, lateral movement and limit the spread of malware.
The concept of segmentation is not new, and numerous papers and resources have been published on the topic. For example:
- Design Secure Network Segmentation Approach - SANS Institute 2021
- Secure Network Design: Micro Segmentation - SANS Institute 2021
- Implement Network Segmentation and Encryption in Cloud Environments - NSA 2024
The pglombardo/pwpush-public-gateway container is an additional layer of security for your organization, helping to protect against potential threats and vulnerabilities.
Deployment Architecture
The public gateway container (pglombardo/pwpush-public-gateway) is designed to be hosted externally, facing your end users, while the full application container (pglombardo/pwpush) is hosted internally for your team’s use.
Architecture Diagram
The following diagram illustrates a typical deployment:
Typical Deployment Flow
- Internal Team uses the full
pglombardo/pwpushcontainer to create pushes - Pushes are stored in a shared database (PostgreSQL or SQLite3 with shared volume)
- External users receive push URLs pointing to the public gateway
- Public gateway (
pglombardo/pwpush-public-gateway) serves push content to external users - Both containers read from the same database to access push data
Configuration
Environment Variables
Important: Except for PWP__OVERRIDE_BASE_URL, the public gateway container should use the same configuration as your internal pwpush container. This ensures both containers connect to the same database and have consistent application settings.
Required Configuration
Both containers must share:
- Database connection (
DATABASE_URL) - Same database for both containers - Encryption key (
PWPUSH_MASTER_KEY) - Same key to decrypt push data - Application settings - Same
settings.ymlor environment variables
Public Gateway Specific
The public gateway container should set:
PWP__OVERRIDE_BASE_URL: 'https://gateway.example.com'
This ensures push URLs generated by the internal container point to the public gateway URL.
Docker Compose Example
Here’s an example docker-compose.yml for a dual-container setup:
services:
# Internal full application (for your team)
pwpush-internal:
image: docker.io/pglombardo/pwpush:stable
restart: unless-stopped
environment:
DATABASE_URL: postgres://pwpush_user:pwpush_passwd@postgres:5432/pwpush_db
PWPUSH_MASTER_KEY: 'your-encryption-key-here'
PWP__OVERRIDE_BASE_URL: 'https://gateway.example.com'
# ... other configuration ...
depends_on:
- postgres
# Public gateway (for external users)
pwpush-gateway:
image: docker.io/pglombardo/pwpush-public-gateway:stable
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
DATABASE_URL: postgres://pwpush_user:pwpush_passwd@postgres:5432/pwpush_db
PWPUSH_MASTER_KEY: 'your-encryption-key-here'
PWP__OVERRIDE_BASE_URL: 'https://gateway.example.com'
TLS_DOMAIN: 'gateway.example.com'
# ... same configuration as internal container ...
# Shared database
postgres:
image: postgres:15
environment:
POSTGRES_USER: pwpush_user
POSTGRES_PASSWORD: pwpush_passwd
POSTGRES_DB: pwpush_db
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
Note: In this example, the internal container doesn’t expose ports externally. Access it through your internal network or VPN.
Database Configuration
Both containers must connect to the same database to share push data. You have two options:
PostgreSQL (Recommended)
PostgreSQL is the recommended database for public gateway deployments because:
- Multiple containers can easily connect to the same database
- Better performance for concurrent access
- No file system sharing required
- Supports distributed deployments
Simply set the same DATABASE_URL for both containers:
# Both containers use the same DATABASE_URL
DATABASE_URL: postgres://pwpush_user:pwpush_passwd@postgres:5432/pwpush_db
SQLite3 with Shared Volume
If using SQLite3, both containers must share the same database file via a Docker volume:
services:
pwpush-internal:
image: docker.io/pglombardo/pwpush:stable
volumes:
- shared-db:/opt/PasswordPusher/db
environment:
DATABASE_URL: sqlite3:///opt/PasswordPusher/db/production.sqlite3
pwpush-gateway:
image: docker.io/pglombardo/pwpush-public-gateway:stable
volumes:
- shared-db:/opt/PasswordPusher/db
environment:
DATABASE_URL: sqlite3:///opt/PasswordPusher/db/production.sqlite3
volumes:
shared-db:
Warning: SQLite3 has limitations with concurrent writes. For production deployments with the public gateway, PostgreSQL is strongly recommended.
Best Practices
Version Management
Always use the same Docker tag for both containers to ensure compatibility:
pwpush-internal:
image: docker.io/pglombardo/pwpush:stable # Use same tag
pwpush-gateway:
image: docker.io/pglombardo/pwpush-public-gateway:stable # Use same tag
Configuration Synchronization
Both containers should use the same configuration:
- Same
settings.ymlfile (if using custom file) OR - Same environment variables
- Same
DATABASE_URL - Same
PWPUSH_MASTER_KEY - Same application settings
Exception: PWP__OVERRIDE_BASE_URL should point to the public gateway URL in both containers.
Security Hardening
- Network isolation: Keep the internal container on a private network
- Firewall rules: Only expose the public gateway ports (80/443) externally
- TLS/SSL: Always use HTTPS for the public gateway (
TLS_DOMAIN) - Secrets management: Use Docker secrets or external secret management for keys
- Regular updates: Keep both containers updated to the same version
Monitoring
- Monitor both containers independently
- Set up alerts for container health
- Monitor database connection status
- Track push delivery success rates
Troubleshooting
Common Issues
Pushes not accessible via public gateway:
- Verify both containers connect to the same database
- Check that
PWP__OVERRIDE_BASE_URLis set correctly - Ensure the encryption key (
PWPUSH_MASTER_KEY) is identical in both containers - Verify the push URL points to the public gateway domain
Users getting logged out:
- Set
SECRET_KEY_BASEto the same value in both containers - This ensures session cookies remain valid across both containers
Database connection errors:
- For PostgreSQL: Verify network connectivity between containers
- For SQLite3: Check volume mount permissions and ensure the volume is shared
- Verify
DATABASE_URLis identical in both containers
Version mismatches:
- Ensure both containers use the same Docker tag (e.g., both
:stableor both:v1.44.0) - Different versions may have incompatible database schemas or features
Configuration differences:
- Compare environment variables between containers
- Ensure all application settings match (except
PWP__OVERRIDE_BASE_URL)
Docker Images
- pglombardo/pwpush - Full application container
- pglombardo/pwpush-public-gateway - Public gateway container
Both images support the same tags (stable, latest, vX.X.X). Always use matching tags for both containers.
See Also
- Installation Guide - Learn how to set up Password Pusher
- DATABASE_URL Configuration - Database connection setup
- Configuration Strategies - How to configure both containers
- Application Encryption - Setting encryption keys
- Proxies - Using reverse proxies with Password Pusher
