Skip to content

avelor-es/vhost

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@avelor/vhost

Apache virtual host manager. Define your sites in a YAML file, run one command, and Apache is configured.

demo

sudo vhost apply
  ✓  catch-all              protected
  ✓  error pages            /var/www/vhost-errors
  ✓  errors conf            vhost-errors.conf

  ✓  avelor.com            managed   /home/avelor/avelor
  ✓  api.avelor.es          managed   :3000
  ✓  app.avelor.es          managed   :4000

  ✓  apache configtest
  ✓  apache reload

Requirements

  • Node.js 18+
  • Apache2 with a2ensite, a2enconf, apache2ctl, mod_headers
  • Debian / Ubuntu

mod_headers is required for the X-Powered-By response header on error pages. Enable it if not already active:

sudo a2enmod headers && sudo systemctl reload apache2

Install

npm install -g @avelor/vhost

Usage

1. Create sites.yml:

vhost init

2. Add your sites:

sites:
  myblog.com:
    aliases: [www.myblog.com]
    mode: static
    root: /var/www/myblog

  api.myapp.com:
    mode: proxy
    port: 3000

3. Apply:

sudo vhost apply

Apache is configured, enabled, and reloaded.


Commands

Command Description
vhost init Create sites.yml in the current directory
vhost new [domain] Add a site interactively (or via flags)
sudo vhost apply [domain] Generate configs, enable sites, reload Apache
sudo vhost remove <domain> Disable and remove a site
vhost check Diff sites.yml against current Apache state
vhost status Show enabled sites

Site configuration

Static site

sites:
  example.com:
    mode: static
    root: /var/www/example.com
    aliases: [www.example.com]   # optional

Reverse proxy

sites:
  api.example.com:
    mode: proxy
    port: 3000
    aliases: [api2.example.com]  # optional

Manual SSL

By default, SSL is left for Certbot to manage. To provide your own certificates:

sites:
  example.com:
    mode: static
    root: /var/www/example.com
    ssl:
      cert: /etc/ssl/certs/example.pem
      key:  /etc/ssl/private/example.key

What apply does

For each site, vhost apply generates a .conf in /etc/apache2/sites-available/ containing:

  • HTTP → HTTPS redirect
  • HTTPS VirtualHost (static or proxy)
  • SSL block (Certbot placeholder or custom cert)
  • Per-site error and access logs

It also sets up two pieces of infrastructure the first time:

Catch-all — any request to an unconfigured domain returns a clean error page instead of falling through to the first VirtualHost alphabetically, which is the default Apache behavior.

Error pages — built-in pages for 400, 401, 403, 404, 405, 408, 429, 500, 502, 503, and 504. Each error code has four variants served via content negotiation:

Accept header Response
text/html Styled HTML page
application/json { "code": 404, "message": "Page not found.", "source": "@avelor/vhost" }
application/xml <error><code>404</code><message>…</message></error>
text/plain 404 Page not found.

All responses include an X-Powered-By: avelor/vhost header. The source field in JSON and the X-Powered-By header make it easy to distinguish vhost error responses from your own API errors.

Useful when the same server hosts both web apps and APIs.


vhost new

Interactive when no flags are given:

$ vhost new

  Domain: api.myapp.com
  Aliases (space-separated, optional):
  Mode: [1] static  [2] proxy → 2
  Proxy port: 3000
  SSL via certbot? [Y/n]:

  ✓  api.myapp.com added to sites.yml

  Next steps:
    sudo vhost apply api.myapp.com
    sudo certbot --apache -d api.myapp.com

Or skip the prompts with flags:

vhost new api.myapp.com --mode proxy --port 3000
vhost new myblog.com --mode static --root /var/www/myblog

Partial flags work too — only the missing fields are asked.


vhost check

Compares sites.yml against Apache's actual state and exits 1 if anything is off.

  ✓  catch-all
  ✓  vhost-errors.conf
  ✓  error pages              /var/www/vhost-errors

  ✓  avelor.com              managed   /home/avelor/avelor
  !  api.avelor.es            manual config   → run: vhost apply api.avelor.es to migrate
  ✖  app.avelor.es            not applied → run: vhost apply app.avelor.es
  !  old.avelor.es            manual config   not in sites.yml

  ✖ 3 issues found.

A site is managed when its .conf was generated by vhost apply. Manual config means the file exists but was written by hand — it works, but sites.yml is not the source of truth yet.


Migrating existing configs

vhost is designed to be adopted gradually. Your existing Apache configs keep working untouched.

The typical flow:

# 1. Set up infrastructure without touching existing sites
sudo vhost apply

# 2. Add one site at a time
vhost new avelor.com --mode static --root /home/avelor/avelor

# 3. Apply only that site — overwrites the manual .conf
sudo vhost apply avelor.com

# 4. Check progress
vhost check

When vhost check shows no manual config warnings, the migration is complete.


License

MIT

About

CLI to manage Apache virtual hosts declaratively: YAML config, catch-all protection, reverse proxy, and built-in error pages

Topics

Resources

License

Stars

Watchers

Forks

Contributors