enr


Nameenr JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryCLI utility for easy nginx reverse proxy configuration with automatic redirect handling.
upload_time2025-09-02 12:08:16
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords nginx reverse-proxy docker cli devops proxy redirect auto-redirect
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ENR = Easy Nginx Redirects

[![CLI Tool](https://img.shields.io/badge/CLI-Tool-green.svg)](https://github.com/pavelsr/enr)
[![Made with Pure Python3](https://img.shields.io/badge/Made%20with-Pure%20Python3-FFCC33.svg?logo=python&logoColor=white)](https://docs.python.org/3/)
[![Nginx as Proxy](https://img.shields.io/badge/Nginx-as%20Proxy-009639.svg?logo=nginx&logoColor=white)](https://nginx.org/)
[![Docker as Deploy](https://img.shields.io/badge/Docker-as%20Deploy-blue.svg?logo=docker&logoColor=white)](https://www.docker.com/)
[![MIT license](https://img.shields.io/badge/MIT-license-9933CC.svg)](https://opensource.org/licenses/MIT)
[![PyPI version](https://img.shields.io/badge/PyPI-version-FFCC33.svg)](https://pypi.org/project/enr/)
[![Contact Developer](https://img.shields.io/badge/Contact-Developer-9933CC.svg?logo=telegram&logoColor=white)](https://t.me/serikoff)

CLI utility for quick & easy generating nginx configuration and running Docker containers with nginx reverse proxy.

Uses only Python standard library without external dependencies. So the utility works immediately after copying files - does not require installation of additional Python packages.

This utility demonstrates the capabilities of nginx's [ngx_http_proxy_module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html) using directives: `proxy_pass`, `proxy_pass_header`, `proxy_intercept_errors`, `proxy_ssl_verify`. These are the specific directives currently implemented, but `ngx_http_proxy_module` module offers many more options. The project serves as an example of a Python wrapper for automatic Docker container configuration and nginx-proxy integration, as well as building Python modules into a single executable script. You can fork this project and customize the nginx and Docker templates for your needs. Pull requests are welcome.

<!-- Created by https://github.com/ekalinin/github-markdown-toc (gh-md-toc README.md)-->

Table of Contents
=================

* [Table of Contents](#table-of-contents)
* [Use Cases](#use-cases)
* [Installation](#installation)
   * [Quick Installation](#quick-installation)
   * [Other installation ways](#other-installation-ways)
      * [Installation from source code](#installation-from-source-code)
      * [Notes about pipx](#notes-about-pipx)
      * [If GitHub is blocked in your network](#if-github-is-blocked-in-your-network)
* [Usage](#usage)
   * [nginx-proxy Compatibility](#nginx-proxy-compatibility)
      * [Integration with nginx-proxy](#integration-with-nginx-proxy)
      * [Quick nginx-proxy deployment](#quick-nginx-proxy-deployment)
* [Under the Hood](#under-the-hood)
   * [Requirements](#requirements)
   * [Dependencies](#dependencies)
   * [Generated Nginx Configuration](#generated-nginx-configuration)
   * [Docker Container Running](#docker-container-running)
* [Features &amp; Roadmap](#features--roadmap)
* [Development &amp; Contributing](#development--contributing)
   * [Version Management](#version-management)
      * [Versioning F.A.Q.](#versioning-faq)
      * [Versioning scheme](#versioning-scheme)
   * [Pre-commit Hooks](#pre-commit-hooks)


<!-- Created by https://github.com/ekalinin/github-markdown-toc (gh-md-toc README.md) -->

# Use Cases

- 🐳 **One-click proxying for any local (Dockerized and non-Dockerized) or remote HTTP or HTTPS service**. This tools runs proxy service as single docker container that is convenient to manage. Support docker networks and hostnames, `host.docker.internal` domain
- 🔒 **Secure Access to Any Service**. Make any web service accessible through HTTPS with just one command, even if it doesn't have security certificates
- 🏗️ **Website Constructor Integration**. Free domain binding for website builders like Tilda, Wix, Webflow, etc. Best for fully static sites, forms may require additional configuration
- 🔗 **Custom Subdomain Links**. Create short, easy-to-remember subdomain links using your own domain name instead of generic shortener services
- 😉 **Your Own Everything**. PRs and forks are welcome

# Installation

## Quick Installation

Since it uses only Python standard library without external dependencies you can install it via:

```bash
curl -fsSL --compressed https://raw.githubusercontent.com/pavelsr/enr/main/enr.pyz > /usr/local/bin/enr && \
    chmod +x /usr/local/bin/enr
```

or you can install it as regular Python module:

```shell
# pipx (recommended)
pipx install enr    # or from GitHub:
pipx install git+https://github.com/pavelsr/enr.git@main

# pip
pip install enr     # or from GitHub:
pip install git+https://github.com/pavelsr/enr.git@main
```

## Other installation ways

<details>
<summary>Other installation ways</summary>

### Installation from source code

```bash
git clone https://github.com/pavelsr/enr.git
cd enr
# Run without installation
./enr.py example.com http://localhost:3000
# Editable install (convenient for test and development):
pip install -e .
# Install development dependencies
pip install -e ".[dev]"
# Install using flit in development mode
flit install --symlink
# Creates enr.pyz from modules:
make build  # Creates enr.pyz from modules
# Or use flit directly
flit build
```

### Notes about pipx 

Since this is a CLI utility, it's recommended to install it using pipx to avoid conflicts with other Python packages:

```bash
# Install pipx if not already installed
python -m pip install --user pipx
python -m pipx ensurepath

# Install ENR
pipx install enr
```

**Advantages of pipx installation:**
- ✅ Isolated environment - no conflicts with other Python packages
- ✅ Easy updates - `pipx upgrade enr`
- ✅ Easy uninstall - `pipx uninstall enr`
- ✅ Global availability - `enr` command available everywhere

### If GitHub is blocked in your network

You can copy the project manually using scp or rsync from a machine where GitHub is NOT blocked:

```bash
# Using scp, only enr.pyz
scp ./enr.pyz user@host.example.com:/usr/local/bin/enr

# Using scp, whole source code
ssh user@host.example.com "mkdir -p ~/enr" && scp -r * user@host.example.com:~/enr/

# Using rsync, whole source code (requires rsync on both machines)
rsync -avz . user@host.example.com:~/enr/
```

**Note**: Replace `user@host.example.com` with your actual server details. The rsync command automatically creates the 'enr' folder if it doesn't exist.

</details>


# Usage

```
usage: enr [-h] [--port PORT] [--container-name CONTAINER_NAME] [--network NETWORK] [--config-dir CONFIG_DIR] [--dry-run] [--force] [--with-letsencrypt] [--version] server_name proxy_pass

positional arguments:
  server_name           Domain name for the server
  proxy_pass            Upstream server URL (e.g., http://localhost:3000)

options:
  -h, --help            show this help message and exit
  --port PORT, -p PORT  Port to listen on (default: 80)
  --container-name CONTAINER_NAME, -n CONTAINER_NAME
                        Docker container name (defaults to server_name)
  --network NETWORK     Docker network name (default: nginx-proxy)
  --config-dir CONFIG_DIR, -d CONFIG_DIR
                        Directory to save nginx config (default: current directory)
  --dry-run             Generate config only, don't run Docker container
  --force, -f           Force overwrite existing config file
  --with-letsencrypt    Automatically add Let's Encrypt environment variables for SSL support
  --version             Show version and exit

Examples:
enr example.com http://<container_name>:3000
enr example.com http://host.docker.internal:8000 --port 3000
enr example.com http://host.docker.internal:8000 --with-letsencrypt
enr shop.example.com https://marketplace.example/seller/<seller_id>
enr example.com https://example.tilda.ws --container-name my-tilda-proxy
enr test.com http://localhost:5000 --dry-run --config-dir ./configs --force
```

## nginx-proxy Compatibility

ENR is specifically designed to work with [nginx-proxy](https://github.com/nginx-proxy/nginx-proxy) - a popular solution for automatic Docker container proxying. ENR automatically:

- Generates compatible nginx configurations
- Runs containers in the `nginx-proxy` network (by default)
- Sets the `VIRTUAL_HOST` environment variable for automatic discovery
- Adds Let's Encrypt variables for SSL certificates when using HTTPS

### Integration with nginx-proxy

```bash
# Start nginx-proxy (if not already running)
docker run -d -p 80:80 -p 443:443 \
  --name nginx-proxy \
  --restart always \
  -v /var/run/docker.sock:/tmp/docker.sock:ro \
  nginxproxy/nginx-proxy

# Imagine that you have non-dockerized service running at 8000 port locally

# Using ENR with nginx-proxy
./enr.py example.com http://host.docker.internal:8000
```

### Quick nginx-proxy deployment

For a complete example of nginx-proxy deployment with Let\x27s Encrypt support, see:
**🔗 https://gitlab.com/pavelsr/nginx-proxy**

This repository contains ready-to-use scripts for quick deployment of nginx-proxy with automatic SSL certificate management.

# Under the Hood

Some Technical Overview about Architecture and Implementation Details

## Requirements

- Python 3.11+ (recommended), 3.10+ (minimum)
- Docker

For full functionality, it is recommended to use:

- **[nginx-proxy](https://github.com/nginx-proxy/nginx-proxy)** - automatic Docker container proxying
- **[nginx-proxy-letsencrypt](https://github.com/nginx-proxy/acme-companion)** - automatic Let's Encrypt SSL certificates

## Dependencies

**The project has no external dependencies** - uses only Python standard library:

- `argparse` - command line argument processing
- `pathlib` - file system path operations
- `subprocess` - running Docker commands
- `str.format()` - nginx configuration formatting (instead of jinja2)
- `zipapp` - building single script (instead of stickytape or PyInstaller)

## Generated Nginx Configuration

The utility creates an nginx configuration of the following type:

```nginx
server {
  server_name example.com;
  listen 80;

  location / {
    proxy_pass http://localhost:3000;
    proxy_pass_header Host;
    proxy_intercept_errors on;
    error_page 301 302 307 = @handle_redirect;
    # recursive_error_pages on;
  }

  location @handle_redirect {
    set $saved_redirect_location '$upstream_http_location';
    proxy_pass $saved_redirect_location;
  }
}
```

## Docker Container Running

After generating the configuration, the utility runs a Docker container with the command:

```bash
# For HTTP
docker run --network nginx-proxy \
  -e VIRTUAL_HOST=example.com \
  -v $(pwd)/example.com.proxy.conf:/etc/nginx/conf.d/default.conf \
  --name example.com \
  -d --restart always nginx:alpine

# For HTTPS (Let's Encrypt variables are automatically added)
docker run --network nginx-proxy \
  -e VIRTUAL_HOST=example.com \
  -e LETSENCRYPT_HOST=example.com \
  -e LETSENCRYPT_EMAIL=443@example.com \
  -v $(pwd)/example.com.proxy.conf:/etc/nginx/conf.d/default.conf \
  --name example.com \
  -d --restart always nginx:alpine
```

# Features & Roadmap

Implemented Features:

- [x] **Easy to use** - one command to set up reverse proxy
- [x] **No external dependencies** - only Python needed (recommended version 3.11)
- [x] **Single script** - can be installed with one curl command, without git/pip/pipx
- [x] **Docker integration** - automatic container running
- [x] **nginx-proxy integration** - nginx-proxy automatically discover containers by `VIRTUAL_HOST`
- [x] **Automatic protocol addition** - automatically adds `http://` to domains without protocol
- [x] **Automatic arguments addition** - automatically adds arguments for support `host.docker.internal`
- [x] **Automatic Let's Encrypt SSL support** - automatically adds environment variables for HTTPS
- [x] **Named configurations** - files are created as `{server_name}.proxy.conf` for better organization
- [x] **Single-source versionin** - `__init__.py`
- [x] **Flit-based build system**
- [x] **Zipapp-based single-file build**

TODO (Roadmap):

- [ ] **Nginx configs as named templates**
- [ ] **More high-level tests**
- [ ] **traefik and other proxy servers integration**

# Development & Contributing

All necessary development commands are available in the Makefile following best practices. To view the complete list of commands, run:

```bash
make help
```

<details>
<summary>Common Makefile commands</summary>


```bash
# Install development dependencies
make install-dev

# Install pre-commit hooks
make pre-commit-install

# Run all checks (formatting, linting, tests)
make check

# Or separately:
make format    # Code formatting
make lint      # Style checking
make test      # Run tests

# Pre-commit hooks
make pre-commit-run    # Manual pre-commit hooks run
make pre-commit-clean  # Clean pre-commit cache

# Clean temporary files
make clean
```
</details>


## Git Guidelines

Before submitting a PR:

1. **Squash your commits** into a single, meaningful commit. E.g.

   ```bash
   git reset --soft HEAD~42
   git commit -m "feat: add new nginx configuration feature"
   ```

2. **Use descriptive commit messages** that explain what the change does

   E.g.
   ```bash
   git commit -m "fix: resolve docker container startup issue (#456)"
   ```

   **Good practice**: Include issue number if one exists (as shown in the example above)

FYI: I prefer [trunk-based development](https://trunkbaseddevelopment.com/) rather than [gitflow branching model](https://nvie.com/posts/a-successful-git-branching-model/)


## Version Management

**To change version ONLY ONE STEP REQUIRED:** Update version in `__init__.py`: `__version__ = "x.y.z"`

**That's it!** All other files automatically get the new version when you run:
- `make build` - builds single script with current version
- `make build-dist` - builds distribution packages with current version

<details>
<summary>Benefits of this approach</summary>

- **Single source of truth**: Version managed in ONE file only (`__init__.py`)
- **Automatic propagation**: All other files automatically get the version from this file
- **Flit dynamic versioning**: Uses flit's built-in `dynamic = ["version"]` feature
- **No git dependency**: Version management works independently of git tags
- **No manual sync needed**: Version is automatically read from module during build
</details>


<details>
<summary>Files that automatically get the version</summary>

```
pyenr/
├── enr/
│ └── init.py # ← MAIN VERSION FILE (change here ONLY)
├── pyproject.toml # ← gets version automatically via flit dynamic
├── setup.py # ← imports version from enr.init (legacy compatibility)
├── enr.pyz # ← single executable script (built via make build)
└── dist/ # ← packages get version automatically
```

</details>

### Versioning F.A.Q.

**Q: How to check current version?**
A: Run `python -c "import enr; print(enr.__version__)"`

**Q: Version didn't update after changing version.py?**
A: Make sure to run `make build` or `make build-dist` after changing the version. Flit will automatically read the new version.

**Q: Flit build failed?**
A: Make sure all files are committed to git, as flit requires a clean git state.

### Versioning scheme

This project follows [Semantic Versioning](https://semver.org/)

## Pre-commit Hooks

The project uses pre-commit hooks for automatic code quality checking before each commit

**What is automatically checked:**
- ✅ Single script build (`make build`)
- ✅ Code formatting (Black)
- ✅ Style checking (ruff)
- ✅ Test running (pytest)
- ✅ Automatic addition of changed `enr.pyz` to commit


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "enr",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "nginx, reverse-proxy, docker, cli, devops, proxy, redirect, auto-redirect",
    "author": null,
    "author_email": "Pavel Serikov <devpasha@proton.me>",
    "download_url": "https://files.pythonhosted.org/packages/dd/61/5b1d77583beb725f6f3a66bd9aaa8b2e033bd8bfd802d2c0e8ee8b281b54/enr-0.1.1.tar.gz",
    "platform": null,
    "description": "ENR = Easy Nginx Redirects\n\n[![CLI Tool](https://img.shields.io/badge/CLI-Tool-green.svg)](https://github.com/pavelsr/enr)\n[![Made with Pure Python3](https://img.shields.io/badge/Made%20with-Pure%20Python3-FFCC33.svg?logo=python&logoColor=white)](https://docs.python.org/3/)\n[![Nginx as Proxy](https://img.shields.io/badge/Nginx-as%20Proxy-009639.svg?logo=nginx&logoColor=white)](https://nginx.org/)\n[![Docker as Deploy](https://img.shields.io/badge/Docker-as%20Deploy-blue.svg?logo=docker&logoColor=white)](https://www.docker.com/)\n[![MIT license](https://img.shields.io/badge/MIT-license-9933CC.svg)](https://opensource.org/licenses/MIT)\n[![PyPI version](https://img.shields.io/badge/PyPI-version-FFCC33.svg)](https://pypi.org/project/enr/)\n[![Contact Developer](https://img.shields.io/badge/Contact-Developer-9933CC.svg?logo=telegram&logoColor=white)](https://t.me/serikoff)\n\nCLI utility for quick & easy generating nginx configuration and running Docker containers with nginx reverse proxy.\n\nUses only Python standard library without external dependencies. So the utility works immediately after copying files - does not require installation of additional Python packages.\n\nThis utility demonstrates the capabilities of nginx's [ngx_http_proxy_module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html) using directives: `proxy_pass`, `proxy_pass_header`, `proxy_intercept_errors`, `proxy_ssl_verify`. These are the specific directives currently implemented, but `ngx_http_proxy_module` module offers many more options. The project serves as an example of a Python wrapper for automatic Docker container configuration and nginx-proxy integration, as well as building Python modules into a single executable script. You can fork this project and customize the nginx and Docker templates for your needs. Pull requests are welcome.\n\n<!-- Created by https://github.com/ekalinin/github-markdown-toc (gh-md-toc README.md)-->\n\nTable of Contents\n=================\n\n* [Table of Contents](#table-of-contents)\n* [Use Cases](#use-cases)\n* [Installation](#installation)\n   * [Quick Installation](#quick-installation)\n   * [Other installation ways](#other-installation-ways)\n      * [Installation from source code](#installation-from-source-code)\n      * [Notes about pipx](#notes-about-pipx)\n      * [If GitHub is blocked in your network](#if-github-is-blocked-in-your-network)\n* [Usage](#usage)\n   * [nginx-proxy Compatibility](#nginx-proxy-compatibility)\n      * [Integration with nginx-proxy](#integration-with-nginx-proxy)\n      * [Quick nginx-proxy deployment](#quick-nginx-proxy-deployment)\n* [Under the Hood](#under-the-hood)\n   * [Requirements](#requirements)\n   * [Dependencies](#dependencies)\n   * [Generated Nginx Configuration](#generated-nginx-configuration)\n   * [Docker Container Running](#docker-container-running)\n* [Features &amp; Roadmap](#features--roadmap)\n* [Development &amp; Contributing](#development--contributing)\n   * [Version Management](#version-management)\n      * [Versioning F.A.Q.](#versioning-faq)\n      * [Versioning scheme](#versioning-scheme)\n   * [Pre-commit Hooks](#pre-commit-hooks)\n\n\n<!-- Created by https://github.com/ekalinin/github-markdown-toc (gh-md-toc README.md) -->\n\n# Use Cases\n\n- \ud83d\udc33 **One-click proxying for any local (Dockerized and non-Dockerized) or remote HTTP or HTTPS service**. This tools runs proxy service as single docker container that is convenient to manage. Support docker networks and hostnames, `host.docker.internal` domain\n- \ud83d\udd12 **Secure Access to Any Service**. Make any web service accessible through HTTPS with just one command, even if it doesn't have security certificates\n- \ud83c\udfd7\ufe0f **Website Constructor Integration**. Free domain binding for website builders like Tilda, Wix, Webflow, etc. Best for fully static sites, forms may require additional configuration\n- \ud83d\udd17 **Custom Subdomain Links**. Create short, easy-to-remember subdomain links using your own domain name instead of generic shortener services\n- \ud83d\ude09 **Your Own Everything**. PRs and forks are welcome\n\n# Installation\n\n## Quick Installation\n\nSince it uses only Python standard library without external dependencies you can install it via:\n\n```bash\ncurl -fsSL --compressed https://raw.githubusercontent.com/pavelsr/enr/main/enr.pyz > /usr/local/bin/enr && \\\n    chmod +x /usr/local/bin/enr\n```\n\nor you can install it as regular Python module:\n\n```shell\n# pipx (recommended)\npipx install enr    # or from GitHub:\npipx install git+https://github.com/pavelsr/enr.git@main\n\n# pip\npip install enr     # or from GitHub:\npip install git+https://github.com/pavelsr/enr.git@main\n```\n\n## Other installation ways\n\n<details>\n<summary>Other installation ways</summary>\n\n### Installation from source code\n\n```bash\ngit clone https://github.com/pavelsr/enr.git\ncd enr\n# Run without installation\n./enr.py example.com http://localhost:3000\n# Editable install (convenient for test and development):\npip install -e .\n# Install development dependencies\npip install -e \".[dev]\"\n# Install using flit in development mode\nflit install --symlink\n# Creates enr.pyz from modules:\nmake build  # Creates enr.pyz from modules\n# Or use flit directly\nflit build\n```\n\n### Notes about pipx \n\nSince this is a CLI utility, it's recommended to install it using pipx to avoid conflicts with other Python packages:\n\n```bash\n# Install pipx if not already installed\npython -m pip install --user pipx\npython -m pipx ensurepath\n\n# Install ENR\npipx install enr\n```\n\n**Advantages of pipx installation:**\n- \u2705 Isolated environment - no conflicts with other Python packages\n- \u2705 Easy updates - `pipx upgrade enr`\n- \u2705 Easy uninstall - `pipx uninstall enr`\n- \u2705 Global availability - `enr` command available everywhere\n\n### If GitHub is blocked in your network\n\nYou can copy the project manually using scp or rsync from a machine where GitHub is NOT blocked:\n\n```bash\n# Using scp, only enr.pyz\nscp ./enr.pyz user@host.example.com:/usr/local/bin/enr\n\n# Using scp, whole source code\nssh user@host.example.com \"mkdir -p ~/enr\" && scp -r * user@host.example.com:~/enr/\n\n# Using rsync, whole source code (requires rsync on both machines)\nrsync -avz . user@host.example.com:~/enr/\n```\n\n**Note**: Replace `user@host.example.com` with your actual server details. The rsync command automatically creates the 'enr' folder if it doesn't exist.\n\n</details>\n\n\n# Usage\n\n```\nusage: enr [-h] [--port PORT] [--container-name CONTAINER_NAME] [--network NETWORK] [--config-dir CONFIG_DIR] [--dry-run] [--force] [--with-letsencrypt] [--version] server_name proxy_pass\n\npositional arguments:\n  server_name           Domain name for the server\n  proxy_pass            Upstream server URL (e.g., http://localhost:3000)\n\noptions:\n  -h, --help            show this help message and exit\n  --port PORT, -p PORT  Port to listen on (default: 80)\n  --container-name CONTAINER_NAME, -n CONTAINER_NAME\n                        Docker container name (defaults to server_name)\n  --network NETWORK     Docker network name (default: nginx-proxy)\n  --config-dir CONFIG_DIR, -d CONFIG_DIR\n                        Directory to save nginx config (default: current directory)\n  --dry-run             Generate config only, don't run Docker container\n  --force, -f           Force overwrite existing config file\n  --with-letsencrypt    Automatically add Let's Encrypt environment variables for SSL support\n  --version             Show version and exit\n\nExamples:\nenr example.com http://<container_name>:3000\nenr example.com http://host.docker.internal:8000 --port 3000\nenr example.com http://host.docker.internal:8000 --with-letsencrypt\nenr shop.example.com https://marketplace.example/seller/<seller_id>\nenr example.com https://example.tilda.ws --container-name my-tilda-proxy\nenr test.com http://localhost:5000 --dry-run --config-dir ./configs --force\n```\n\n## nginx-proxy Compatibility\n\nENR is specifically designed to work with [nginx-proxy](https://github.com/nginx-proxy/nginx-proxy) - a popular solution for automatic Docker container proxying. ENR automatically:\n\n- Generates compatible nginx configurations\n- Runs containers in the `nginx-proxy` network (by default)\n- Sets the `VIRTUAL_HOST` environment variable for automatic discovery\n- Adds Let's Encrypt variables for SSL certificates when using HTTPS\n\n### Integration with nginx-proxy\n\n```bash\n# Start nginx-proxy (if not already running)\ndocker run -d -p 80:80 -p 443:443 \\\n  --name nginx-proxy \\\n  --restart always \\\n  -v /var/run/docker.sock:/tmp/docker.sock:ro \\\n  nginxproxy/nginx-proxy\n\n# Imagine that you have non-dockerized service running at 8000 port locally\n\n# Using ENR with nginx-proxy\n./enr.py example.com http://host.docker.internal:8000\n```\n\n### Quick nginx-proxy deployment\n\nFor a complete example of nginx-proxy deployment with Let\\x27s Encrypt support, see:\n**\ud83d\udd17 https://gitlab.com/pavelsr/nginx-proxy**\n\nThis repository contains ready-to-use scripts for quick deployment of nginx-proxy with automatic SSL certificate management.\n\n# Under the Hood\n\nSome Technical Overview about Architecture and Implementation Details\n\n## Requirements\n\n- Python 3.11+ (recommended), 3.10+ (minimum)\n- Docker\n\nFor full functionality, it is recommended to use:\n\n- **[nginx-proxy](https://github.com/nginx-proxy/nginx-proxy)** - automatic Docker container proxying\n- **[nginx-proxy-letsencrypt](https://github.com/nginx-proxy/acme-companion)** - automatic Let's Encrypt SSL certificates\n\n## Dependencies\n\n**The project has no external dependencies** - uses only Python standard library:\n\n- `argparse` - command line argument processing\n- `pathlib` - file system path operations\n- `subprocess` - running Docker commands\n- `str.format()` - nginx configuration formatting (instead of jinja2)\n- `zipapp` - building single script (instead of stickytape or PyInstaller)\n\n## Generated Nginx Configuration\n\nThe utility creates an nginx configuration of the following type:\n\n```nginx\nserver {\n  server_name example.com;\n  listen 80;\n\n  location / {\n    proxy_pass http://localhost:3000;\n    proxy_pass_header Host;\n    proxy_intercept_errors on;\n    error_page 301 302 307 = @handle_redirect;\n    # recursive_error_pages on;\n  }\n\n  location @handle_redirect {\n    set $saved_redirect_location '$upstream_http_location';\n    proxy_pass $saved_redirect_location;\n  }\n}\n```\n\n## Docker Container Running\n\nAfter generating the configuration, the utility runs a Docker container with the command:\n\n```bash\n# For HTTP\ndocker run --network nginx-proxy \\\n  -e VIRTUAL_HOST=example.com \\\n  -v $(pwd)/example.com.proxy.conf:/etc/nginx/conf.d/default.conf \\\n  --name example.com \\\n  -d --restart always nginx:alpine\n\n# For HTTPS (Let's Encrypt variables are automatically added)\ndocker run --network nginx-proxy \\\n  -e VIRTUAL_HOST=example.com \\\n  -e LETSENCRYPT_HOST=example.com \\\n  -e LETSENCRYPT_EMAIL=443@example.com \\\n  -v $(pwd)/example.com.proxy.conf:/etc/nginx/conf.d/default.conf \\\n  --name example.com \\\n  -d --restart always nginx:alpine\n```\n\n# Features & Roadmap\n\nImplemented Features:\n\n- [x] **Easy to use** - one command to set up reverse proxy\n- [x] **No external dependencies** - only Python needed (recommended version 3.11)\n- [x] **Single script** - can be installed with one curl command, without git/pip/pipx\n- [x] **Docker integration** - automatic container running\n- [x] **nginx-proxy integration** - nginx-proxy automatically discover containers by `VIRTUAL_HOST`\n- [x] **Automatic protocol addition** - automatically adds `http://` to domains without protocol\n- [x] **Automatic arguments addition** - automatically adds arguments for support `host.docker.internal`\n- [x] **Automatic Let's Encrypt SSL support** - automatically adds environment variables for HTTPS\n- [x] **Named configurations** - files are created as `{server_name}.proxy.conf` for better organization\n- [x] **Single-source versionin** - `__init__.py`\n- [x] **Flit-based build system**\n- [x] **Zipapp-based single-file build**\n\nTODO (Roadmap):\n\n- [ ] **Nginx configs as named templates**\n- [ ] **More high-level tests**\n- [ ] **traefik and other proxy servers integration**\n\n# Development & Contributing\n\nAll necessary development commands are available in the Makefile following best practices. To view the complete list of commands, run:\n\n```bash\nmake help\n```\n\n<details>\n<summary>Common Makefile commands</summary>\n\n\n```bash\n# Install development dependencies\nmake install-dev\n\n# Install pre-commit hooks\nmake pre-commit-install\n\n# Run all checks (formatting, linting, tests)\nmake check\n\n# Or separately:\nmake format    # Code formatting\nmake lint      # Style checking\nmake test      # Run tests\n\n# Pre-commit hooks\nmake pre-commit-run    # Manual pre-commit hooks run\nmake pre-commit-clean  # Clean pre-commit cache\n\n# Clean temporary files\nmake clean\n```\n</details>\n\n\n## Git Guidelines\n\nBefore submitting a PR:\n\n1. **Squash your commits** into a single, meaningful commit. E.g.\n\n   ```bash\n   git reset --soft HEAD~42\n   git commit -m \"feat: add new nginx configuration feature\"\n   ```\n\n2. **Use descriptive commit messages** that explain what the change does\n\n   E.g.\n   ```bash\n   git commit -m \"fix: resolve docker container startup issue (#456)\"\n   ```\n\n   **Good practice**: Include issue number if one exists (as shown in the example above)\n\nFYI: I prefer [trunk-based development](https://trunkbaseddevelopment.com/) rather than [gitflow branching model](https://nvie.com/posts/a-successful-git-branching-model/)\n\n\n## Version Management\n\n**To change version ONLY ONE STEP REQUIRED:** Update version in `__init__.py`: `__version__ = \"x.y.z\"`\n\n**That's it!** All other files automatically get the new version when you run:\n- `make build` - builds single script with current version\n- `make build-dist` - builds distribution packages with current version\n\n<details>\n<summary>Benefits of this approach</summary>\n\n- **Single source of truth**: Version managed in ONE file only (`__init__.py`)\n- **Automatic propagation**: All other files automatically get the version from this file\n- **Flit dynamic versioning**: Uses flit's built-in `dynamic = [\"version\"]` feature\n- **No git dependency**: Version management works independently of git tags\n- **No manual sync needed**: Version is automatically read from module during build\n</details>\n\n\n<details>\n<summary>Files that automatically get the version</summary>\n\n```\npyenr/\n\u251c\u2500\u2500 enr/\n\u2502 \u2514\u2500\u2500 init.py # \u2190 MAIN VERSION FILE (change here ONLY)\n\u251c\u2500\u2500 pyproject.toml # \u2190 gets version automatically via flit dynamic\n\u251c\u2500\u2500 setup.py # \u2190 imports version from enr.init (legacy compatibility)\n\u251c\u2500\u2500 enr.pyz # \u2190 single executable script (built via make build)\n\u2514\u2500\u2500 dist/ # \u2190 packages get version automatically\n```\n\n</details>\n\n### Versioning F.A.Q.\n\n**Q: How to check current version?**\nA: Run `python -c \"import enr; print(enr.__version__)\"`\n\n**Q: Version didn't update after changing version.py?**\nA: Make sure to run `make build` or `make build-dist` after changing the version. Flit will automatically read the new version.\n\n**Q: Flit build failed?**\nA: Make sure all files are committed to git, as flit requires a clean git state.\n\n### Versioning scheme\n\nThis project follows [Semantic Versioning](https://semver.org/)\n\n## Pre-commit Hooks\n\nThe project uses pre-commit hooks for automatic code quality checking before each commit\n\n**What is automatically checked:**\n- \u2705 Single script build (`make build`)\n- \u2705 Code formatting (Black)\n- \u2705 Style checking (ruff)\n- \u2705 Test running (pytest)\n- \u2705 Automatic addition of changed `enr.pyz` to commit\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "CLI utility for easy nginx reverse proxy configuration with automatic redirect handling.",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://github.com/pavelsr/enr",
        "Repository": "https://github.com/pavelsr/enr"
    },
    "split_keywords": [
        "nginx",
        " reverse-proxy",
        " docker",
        " cli",
        " devops",
        " proxy",
        " redirect",
        " auto-redirect"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "875b1c19c4cc9214a5c47a6b92aedc6a2d36c49414051219b7289e7ad85f1165",
                "md5": "e52a36599d12cc71cbe909d9e42d7af5",
                "sha256": "8cfd1846265b45bcfc0552ddc2556149b3539aa0d5006976ba1b4a056d813141"
            },
            "downloads": -1,
            "filename": "enr-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e52a36599d12cc71cbe909d9e42d7af5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 12340,
            "upload_time": "2025-09-02T12:08:15",
            "upload_time_iso_8601": "2025-09-02T12:08:15.681147Z",
            "url": "https://files.pythonhosted.org/packages/87/5b/1c19c4cc9214a5c47a6b92aedc6a2d36c49414051219b7289e7ad85f1165/enr-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "dd615b1d77583beb725f6f3a66bd9aaa8b2e033bd8bfd802d2c0e8ee8b281b54",
                "md5": "080b4dd2949e34fd3de46f8acf1502c7",
                "sha256": "61052a8397532598ebaa1c4d6cb5a9f39e2501ac52e90c4a514d4913a5dd9700"
            },
            "downloads": -1,
            "filename": "enr-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "080b4dd2949e34fd3de46f8acf1502c7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 19052,
            "upload_time": "2025-09-02T12:08:16",
            "upload_time_iso_8601": "2025-09-02T12:08:16.920653Z",
            "url": "https://files.pythonhosted.org/packages/dd/61/5b1d77583beb725f6f3a66bd9aaa8b2e033bd8bfd802d2c0e8ee8b281b54/enr-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-02 12:08:16",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "pavelsr",
    "github_project": "enr",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "enr"
}
        
Elapsed time: 0.83709s