ap-application-load-balancer

AP Application Load Balancer Components

GitHub: fititnt/ap-application-load-balancer Website: ap-application-load-balancer.etica.ai

ALB components


TL;DR on ALB Components

For full details, check defaults/main.yml. The main part for a overview is:

### AP-ALB Components overview _________________________________________________
# The defaults of v0.7.4+ will use: Apps, HAProxy, Logrotate, OpenResty
# You can enable/disable components. Or explicity enforce on your configuration
alb_manange_all: yes
alb_manange_haproxy: yes
alb_manange_openresty: yes
alb_manange_ufw: no

## Sanity Check run at very beginning
alb_manange_sanitycheck: yes

## Note: the next options is better leave it alone
alb_manange_apps: ""
alb_manange_logrotate: ""


Shared options

Shared options are how we call variable conventions that could be used as default option to improve more specific ALB Components or your own custom implementation.

ACME

These options are re-used by components that manange Automatic Certificate Management Environment (ACME). See ACME on Wikipedia and RFC 8555.

### AP-ALB ACME ________________________________________________________________
# BY USING Let's Encrypt, even if automated for you, you AGREE with
# Let’s Encrypt Subscriber Agreement at https://letsencrypt.org/repository/

alb_acme_production: true

alb_acme_rule_ips_allowed: false # ACME (Let's Encript at least) will HTTPS for IPs, so don't even try

# Exact match
alb_acme_rule_whitelist: []
alb_acme_rule_whitelist_file: '' # not implemented... yet
alb_acme_rule_blacklist: []
alb_acme_rule_blacklist_file: '' # not implemented... yet

# Suffix match (e.g. for subdomains) and prefix match (e.g. if any full domain, if start with these values)
alb_acme_rule_whitelist_suffix: []
alb_acme_rule_whitelist_prefix: []
alb_acme_rule_blacklist_suffix: []
alb_acme_rule_blacklist_prefix: []

# alb_acme_rule_lua inject custom lua inside GUI/lua-resty-auto-ssl allow_domain function.
alb_acme_rule_lua: |
  -- FILE: /usr/local/openresty/nginx/conf/nginx.conf
  -- NGINX CONTEXT: http/init_by_lua_block/auto_ssl:set("allow_domain", function(domain)
  -- See https://github.com/GUI/lua-resty-auto-ssl
  -- Note 1: Inside lua blocks (like this one) "--" is used for start comments
  --       and not "#"
  -- Note 2: your custom code should 'return true' or 'return false'

# alb_acme_rule_last define your "default" behavior for what was not explicitly
# whitelisted/blacklisted
alb_acme_rule_last: true

# This value is infered from alb_acme_production. But you can customize yourself
alb_acme_url: "https://acme-v02.api.letsencrypt.org/directory"
Example using ACME

alb_node_storage_driver: 'consul'
# alb_node_storage_driver also define where each node will store it's HTTPS secrets. Values:
#  - 'file'
#    - This is the default, uses /etc/resty-auto-ssl
#  - 'consul'
#  - 'custom'
#    - Tip: alb_node_storage_custom_luarestautossl example you can use Redis storage

alb_acme_production: true

alb_acme_rule_ips_allowed: false
alb_acme_rule_whitelist:
  - "example.org"
  - ""
alb_acme_rule_blacklist:
  - "example.com"
  - "old-domain-that-should-not-try-renew.com"

alb_acme_rule_whitelist_suffix:
  - ".example.org"
  - ".nip.io"
  - ".xip.io"
  - "."

alb_acme_rule_blacklist_suffix:
  - ".sslip.io"

alb_acme_rule_last: false

# If debugging, consider using multitail with these paths:
#     multitail -ci white /var/log/alb/access.log -ci yellow -I /var/log/alb/error.log  -ci blue -I /var/log/alb/letsencrypt.log

Applications/Sysapplications variables

Content moved to ../rules/index.md.

Autentication Credentials

alb_auth_users:
  - username: Admin1
    password: "plain-password"
  - username: Admin2
    password: "plain-password2"
  - username: "old-user-that-should-be-removed"
    password: "anotheranotherpass"
    state: absent
  - username: SuperUser2
    password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      62313365396662343061393464336163383764373764613633653634306231386433626436623361
      6134333665353966363534333632666535333761666131620a663537646436643839616531643561
      63396265333966386166373632626539326166353965363262633030333630313338646335303630
      3438626666666137650a353638643435666633633964366338633066623234616432373231333331
      6564

Bastion Hosts

alb_bastion_hosts:
  - ip: 192.0.2.255
    name: "My Bastion Host"

DMZ (DeMilitarized Zone)

alb_dmz:
 - ip: 203.0.113.1
   name: my_apps_server
 - ip: 203.0.113.2
   name: my_db_server
 - ip: 203.0.113.3
   name: any_other_server_inside_the_network

Jump Server

alb_jump_boxes:
  - ip: 192.0.2.10
    name: "my jumpbox server"

Apps

Tip: apps requires OpenResty.

For simplification each group of rules is called “app” because most of the time this is the case. The parameter app_alb_strategy defines wich OpenResty configuration template will be used as base to generate each file on /opt/alb/apps/.conf.

Protip: if you already have experience editing NGinx configurations, the way AP-ALB automate the work for you will be very familiar.

ALB Strategies

For full list of ALB Strategies, look at templates/alb-strategy

files-local

Strategy to serve static files from the same server where the ALB is located.

    alb_apps:

      - app_uid: "static-files"
        app_domain: "assets.example.org"
        app_root: "/var/www/html"
        app_forcehttps: yes
        app_alb_strategy: "files-local"

See templates/alb-strategy/files-local.conf.j2.

hello-world

Hello world is a simple strategy to test one App/Sysapp. It can be specially useful to obtain SSL Certificates or already have some placeholder.

If app_debug: true or alb_forcedebug: yes it can be used to give more information.

    alb_apps:

      - app_uid: "hello-world"
        app_domain: "debug.example.org"
        app_domain_extras:
          - hello-world.example.com
          - hello-world.*
        app_debug: true
        app_alb_strategy: "hello-world"

See templates/alb-strategy/hello-world.conf.j2.

minimal

The app_alb_strategy: minimal is not as raw as the raw, but is the last step before what is given by files-local or proxy. Some applications could require so much fine tunning that is just simpler to give access to you implement app_alb_raw and/or app_alb_raw_file, BUT all other configurations, like paths to load balancer, logs, Automatic HTTPS, etc be handled for you.

    alb_apps:
      - app_uid: "hello-world-minimal"
        app_domain: "hello-world-minimal..nip.io"
        app_alb_strategy: "minimal"
        app_alb_raw_file: "templates/example_app_alb_raw_file.conf.j2"
        app_alb_raw: >
          charset_types application/json;
          default_type application/json;

          location = /status {
              stub_status;
              allow all;
          }
          location = /ping {
              access_log off;
              return 200 "pong\n";
          }
          location = / {
              content_by_lua_block {
                 local cjson = require "cjson"
                 ngx.status = ngx.HTTP_OK
                 ngx.say(cjson.encode({
                     msg = "Hello, hello-world-minimal! (from app_alb_raw)",
                     status = 200
                 }))
              }
          }

See templates/alb-strategy/hello-world.conf.j2.

proxy

Use ALB as reverse proxy.

    alb_apps:

      - app_uid: "minio"
        app_domain: "minio.example.org"
        app_alb_strategy: "proxy"
        app_forcehttps: yes
        app_alb_proxy: ":::9091"

See templates/alb-strategy/proxy.conf.j2.

raw

raw strategy is similar to minimal, but you have full control using app_alb_raw and/or app_alb_raw_file.

This strategy can be specially useful on upgrades of AP-ALB where new configurations could break some old functionality and you have no time to make the new upgrades for some specific app.

Bootstrap

Bootstrap Python installation

Ansible requires Python (better if is Python3) and for very new hosts, you may get this error message: “the module failed to execute correctly you probably need to set the interpreter”.

This means that you need to manually install python on your target hosts. BUT you can use AP-ALB to use try raw – Executes a low-down and dirty command and do it for you.

Check example/bootstrap-even-python.yml for more details. It’s not necessary (and not recommended) leave alb_boostrap_python: "force" saved on playbooks, since this part in special of the ALB/Bootstrap have very limited safety checks if you missuse. You can temporaly use via CLI extra commands, like this:

ansible-playbook my-playbook-with-gather_facts-false.yml -i example.org, -e='alb_boostrap_python=force'

Note, if even this fails, do it manually.

HAProxy

Please check NLB Internals (working draft).

HAProxy stats page

Please also check Check defaults/main.yml section # AP-ALB Component: HAProxy | HAProxy Stats.

Here a full example that will make you access HAProxy Status page from a host example.com at http://example.com:8404/haproxy?stats from very specific IPs and requiring user and passwords from alb_auth_users.

alb_manange_haproxy: yes

alb_haproxy_stats_enabled: yes
alb_haproxy_stats_ip: 0.0.0.0 # 0.0.0.0 means exposed for everyone. Use firewall!
alb_haproxy_stats_port: 8404
alb_haproxy_stats_uri: "/haproxy?stats"
alb_haproxy_stats_realm: ": "

# If informed, HAProxy Stats page will allow access from alb_trusted_hosts_ips:
# (localhost + alb_dmz + alb_bastion_hosts) [Does not include alb_jump_boxes]
alb_dmz:
  - ip: 167.86.127.220
    name: apps_server_apalbdemo
  - ip: 167.86.127.225
    name: db_server_apalbdemo
alb_bastion_hosts:
  - ip: 177.126.157.169
    name: aguia-pescadora-delta.etica.ai

# If informed, HAProxy Stats page will require require user and password from alb_auth_users
alb_auth_users:
  - username: Admin1
    password: "plain-password"
  - username: Admin2
    password: "plain-password2"
  - username: SuperUser2
    password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      62313365396662343061393464336163383764373764613633653634306231386433626436623361
      6134333665353966363534333632666535333761666131620a663537646436643839616531643561
      63396265333966386166373632626539326166353965363262633030333630313338646335303630
      3438626666666137650a353638643435666633633964366338633066623234616432373231333331
      6564


# As ALB 0.7.4, without further customizations, if both alb_trusted_hosts_ips
# and alb_auth_users are provided, even from these IPs you is required to
# provide a password

Security information: Even if you do not have UFW enabled and forgot to setup your own firewall (or use one from your cloud privider) the default behavior of ALB stats page is still require the result of alb_trusted_hosts_ips (this result is defined on vars/main.yml).

HAProxy TLS Termination

At least for the ALB v0.6.1-alpha we do not provice automated way to implement automatic HTTPS using only HAProxy. We implement using lua-resty-auto-ssl.

Still possible to do it but you will need to implement additional logic.

Logrotate

Logrotate is enabled by default on defaults/main.yml when alb_manange_openresty: yes or alb_manange_apps: yes.

You can selectively disable with alb_manange_logrotate: no, but would be recommended implement your own log strategy.

Check tasks/logrotate/logrotate.yml.

OpenResty

Please check ALB Internals.

Run OpenResty without HAProxy

Strong suggestion: the memory footprint of using HAproxy in front of OpenResty is not a good reason to not leave enabled.

OpenResty, out of the box, have default values assuming HAProxy is installed on the same host in front. If want to change this behavior, consider change at least these variables from the defaults on defaults/main.yml:

alb_manange_haproxy: no
alb_openresty_ip: 0.0.0.0
alb_openresty_httpport: 80
alb_openresty_httpsport: 443

lua-resty-auto-ssl

GUI/lua-resty-auto-ssl used with OpenResty to allow Automatic HTTPS on-the-fly.

See Shared Option: ACME to see rules that affect this implementation.

SanityCheck

This ALB component (enabled by default) will run at very start of a play and try to do some very basic sanity checks that have a tendency to cause a node or a entire cluster to enter on a non-operational state via human mistakes on ALB configurations.

Status

This mode is safe run, and can be used even in Check Mode (“Dry Run”) with --check parameter. It’s also expected (and you will be informed) that some checks will soft fail (like trying to check alb_apps.facts) on a node that does not have apps.

# Note: by default the standard status checks are always run at the end of a
#       successful. This may slow down your run, but we're consider a good
#       default.

#       BUT you may have a system so broken that not even the status checks
#       will start or you want call it directly

# This skips other steps and go diretly to minimal status checks
ansible-playbook playbook.yml -i hosts.yml --check --tags="alb-status"

# TODO: implement a mode even more verbose:
ansible-playbook playbook.yml -i hosts.yml --check --tags="alb-status-full"

Sysapps

Sysapps implement near the same options than Apps, but their focus is namespace apps that are not intended for end user usage. The adantages of this is apply default access control for all sysapps and also when running very large deployment you could choose run only the Apps or the Sysapps rules.


    # alb_sysapps_default not implemented yet
    alb_sysapps_default:
      app_forcehttps: no
      app_basicauth_file: "/opt/alb/sysapps/.htaccess"

    # If defined, will create /opt/alb/sysapps/.htaccess just once
    alb_sysapps_htpassword : ""

    alb_sysapps:
      - app_uid: "consul"
        app_domain: "consul..nip.io"
        app_domain_extras:
          - consul.*
        app_alb_strategy: "proxy"
        app_forcehttps: no
        app_alb_proxy: "http://127.0.0.1:8500"

      - app_uid: "haproxy"
        app_domain: "haproxy..nip.io"
        app_domain_extras:
          - haproxy.*
        app_alb_strategy: "proxy"
        app_alb_proxy: "http://127.0.0.1:"

New on v0.8.6-alpha: internally ALB will merge alb_sysapps_alb + alb_sysapps_always + alb_sysapps and alb_app_always + alb_apps. Ansible default behavior when the same variable is defined default and then some hosts also specify the variable is override. To make it easier for who want some apps/sysapps be on all nodes on a datacenter (and to avoid you use advanced features like hash_behaviour or implement plugins like leapfrogonline/ansible-merge-vars) we suggest use as convention alb_sysapps_always and alb_app_always.

ALB optionated sysapps

The variable alb_sysapps_alb if defined, will inject some sysapps before alb_sysapps_always and alb_sysapps.

UFW

To avoid acidental use, this feature is not enabled by default (and will never be on any future release). alb_manange_ufw: yes is explicitly required.

Protip: Check Mode (“Dry Run”) with --tags alb-ufw --check. This will test changes without applying.


# Allow ALB/UFW manage (required)
alb_manange_ufw: yes

# @see https://en.wikipedia.org/wiki/DMZ_(computing)
# ALB/UFW will use alb_dmz to make all traffic FROM/TO to this machine free
alb_dmz:
  - ip: 167.86.127.220
    name: apps_server_apalbdemo
  - ip: 167.86.127.225
    name: db_server_apalbdemo

# @see https://en.wikipedia.org/wiki/Bastion_host
# ALB/UFW will use alb_bastion_hosts to make all traffic FROM/TO to this machine free
# This behavior could change on future to make it more configurable
alb_bastion_hosts:
  - ip: 177.126.157.169
    name: aguia-pescadora-delta.etica.ai

# @see https://en.wikipedia.org/wiki/Jump_server
# ALB/UFW will use alb_jump_boxes to make all traffic FROM/TO to this machine free
# This behavior could change on future to make it more configurable
alb_jump_boxes:
  - ip: 192.0.2.10
    name: TEST-NET-1 (example IP)

Applying only firewall rules on a specific server (i.e. do not install HAProxy, OpenResty…)

Is possible to reuse the YAML syntax of AP-ALB to only configure firewall of a server, without installing HAProxy, OpenResty, creating /opt/alb/apps/ folders etc.

This could be useful for database servers.

# Works on ALB v0.6.1-alpha. Future versions may require other options disabled
alb_manange_haproxy: no
alb_manange_openresty: no
alb_manange_ufw: yes

# Use alb_ufw_rules, alb_dmz, alb_bastion_hosts, alb_jump_boxes etc

External documentation about UFW and Ansible