├── .ansible-lint ├── .gitignore ├── .gitmodules ├── README.md ├── ansible.cfg ├── behave ├── README.md ├── steps │ └── steps_webserver.py └── webserver.feature ├── filter_plugins ├── derive_mac_addr.py ├── remove_filter.py └── resolve_filter.py ├── group_vars ├── all.yml ├── dnsserver.yml ├── eventsserver.yml └── webserver.yml ├── hosts ├── lib ├── hosts.py ├── slpp.py └── tests │ ├── hosts.json │ ├── site.conf │ └── tests.py ├── library └── fastd_key ├── playbooks ├── backbone.yml ├── dnsserver.yml ├── downlinks.yml ├── eventsserver.yml ├── ffmapserver.yml ├── standardserver.yml ├── vpnserver.yml └── webserver.yml ├── requirements.txt ├── roles ├── apache │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── anon-logs.conf │ │ ├── default-dir-options.conf │ │ ├── deflate-more-types.conf │ │ ├── logrotate-apache2-user │ │ ├── ocsp-stapling.conf │ │ ├── proxy.conf │ │ └── user-php-exec.conf │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── 000-default.conf ├── apt │ ├── README.md │ ├── files │ │ ├── apt-periodic.conf │ │ ├── apt-recommends.conf │ │ └── unattended-upgrades-dpkg.conf │ └── tasks │ │ └── main.yml ├── automysqlbackup │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── backbone-gre │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── firewall.sh │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ └── interfaces │ └── vars │ │ └── main.yml ├── batman-adv-14 │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── dkms-batman-adv-downgrade │ └── tasks │ │ └── main.yml ├── batman-adv-interface │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── if-pre-up │ │ └── if-pre-up-legacy │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── interfaces ├── batman-adv │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── caddy │ ├── README.md │ ├── files │ │ └── caddy.service.patch │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── Caddyfile │ │ └── hostname.caddy ├── chrony │ ├── README.md │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── chrony.conf │ │ └── firewall.sh ├── dnsmasq │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── dnsmasq-hook.sh │ │ ├── dnsmasq-tmpfs.service │ │ └── dnsmasq-tmpfs.timer │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── dnsmasq.conf │ │ └── firewall.sh ├── downlink-firewall │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── ipv6-neigh-cache-negative.service │ │ └── ipv6-neigh-cache-negative.sh │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── downloadsite │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── htaccess │ │ └── rsync.service │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ └── rsyncd.conf ├── etckeeper-post │ └── tasks │ │ └── main.yml ├── etckeeper-pre │ └── tasks │ │ └── main.yml ├── etckeeper │ ├── README.md │ ├── files │ │ └── git-config │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── eventswebsite │ ├── README.md │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── index.html ├── exit-ipv4 │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── 10-allow-gre │ │ └── 10-allow-ipip │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── default.yml │ │ ├── generic.yml │ │ └── main.yml │ └── templates │ │ ├── default │ │ ├── 10-tcpmss-ipv4 │ │ ├── 20-exit-ipv4 │ │ └── up.sh │ │ └── generic │ │ └── interface ├── exit-ipv6 │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── bird-radv.conf │ │ └── firewall.sh │ └── vars │ │ └── main.yml ├── fail2ban │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── fastd │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── blacklist.yml │ │ ├── instance.yml │ │ └── main.yml │ └── templates │ │ ├── fastd.conf │ │ ├── firewall.sh │ │ ├── interfaces │ │ ├── peer.conf │ │ ├── update-fastd-blacklist@.service │ │ └── update-fastd-blacklist@.timer ├── firewall │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── 00-base │ │ ├── 90-established │ │ ├── 99-reject │ │ ├── firewall.service │ │ └── ipv4-netfilter-ip-conntrack-max.conf │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── included.yml │ │ └── main.yml │ └── templates │ │ └── init.sh ├── freifunkmanager │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── caddy │ │ ├── config.toml │ │ └── freifunkmanager.service ├── gatemon │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ └── php-fcgi-starter ├── git │ └── tasks │ │ └── main.yml ├── go │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── go.sh ├── grafana │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── Short.json │ │ └── json │ │ │ ├── global.json │ │ │ └── node.json │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ ├── caddy │ │ └── grafana.ini ├── group-webusers │ └── tasks │ │ └── main.yml ├── influxdb │ ├── files │ │ └── firewall.sh │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── influxdb.conf ├── letsencrypt │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── acme-challenge.conf │ │ ├── config │ │ ├── cronjob │ │ └── hook.sh │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── main-bridge │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── bridge-filter.conf │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── interfaces │ │ └── main-bridge-ip-neigh-tuning.conf ├── mesh-announce │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── cronjob │ │ ├── firewall.sh │ │ └── service ├── meshviewer │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── apache.yml │ │ ├── geojson.yml │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ ├── geojson-update.sh │ │ └── geojson.cronjob ├── monitoring-client │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── 98mk-apt │ │ ├── authorized_keys │ │ └── plugins │ │ │ ├── check_conntrack.sh │ │ │ ├── check_git_status │ │ │ ├── check_release_eol │ │ │ └── check_rkhunter │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── motd │ ├── files │ │ ├── add-motd-tail │ │ ├── figlet │ │ └── remove-motd-dynamic │ └── tasks │ │ └── main.yml ├── mysql-server │ ├── README.md │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── nginx │ ├── files │ │ └── firewall.sh │ └── tasks │ │ └── main.yml ├── nodejs │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── nodemon │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ └── php-fcgi-starter ├── non_persistent_logging │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── nsd │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── cronjob │ │ ├── firewall.sh │ │ ├── update-dns-zones.sh │ │ └── zonegen.py │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── nsd.conf ├── nullmailer │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── remotes ├── openssh │ ├── README.md │ ├── files │ │ └── firewall.sh │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── php │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── restic │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── backup-restic │ │ └── backup-restic.default │ └── tasks │ │ └── main.yml ├── rkhunter │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── router-bird │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── bird.conf │ │ ├── bird6.conf │ │ ├── firewall.sh │ │ ├── internal_ipv4.conf │ │ └── internal_ipv6.conf │ └── vars │ │ └── main.yml ├── ruby │ └── tasks │ │ └── main.yml ├── speedtest │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── nginx.conf │ └── tasks │ │ └── main.yml ├── sudo │ ├── README.md │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── system │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── autologin.conf │ │ └── sysctl.d │ │ │ ├── dmesg-restrict.conf │ │ │ ├── fs-file-max.conf │ │ │ ├── ipv4-arp-ignore.conf │ │ │ ├── ipv4-forwarding.conf │ │ │ ├── ipv4-icmp-errors-use-inbound-ifaddr.conf │ │ │ ├── ipv4-ignore-icmp-bogus-error-responses.conf │ │ │ ├── ipv4-ignore-icmp-broadcast.conf │ │ │ ├── ipv4-tcp-abort-on-overflow.conf │ │ │ ├── ipv4-tcp-fin-timeout.conf │ │ │ ├── ipv4-tcp-syn-retries.conf │ │ │ ├── ipv4-tcp-synack-retries.conf │ │ │ ├── ipv4-tcp-syncookies.conf │ │ │ ├── ipv6-forwarding.conf │ │ │ ├── kernel-core-uses-pid.conf │ │ │ ├── kernel-panic.conf │ │ │ ├── kernel-pid-max.conf │ │ │ ├── kernel-shm.conf │ │ │ ├── kernel-sysrq.conf │ │ │ ├── no-ipv4-redirects.conf │ │ │ ├── no-ipv4-rp-filter.conf │ │ │ ├── no-ipv6.conf │ │ │ ├── vm-min-free-kbytes.conf │ │ │ ├── vm-overcommit.conf │ │ │ └── vm-swappiness.conf │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ ├── main.yml │ │ └── vm.yml │ └── templates │ │ └── grub-serial.cfg ├── tasksite │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── htaccess │ │ └── run-log │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache-tasks.conf │ │ ├── ffhb.conf.php │ │ ├── phabricator-daemon-file │ │ ├── phabricator.service │ │ ├── php-extopts.ini │ │ └── php-fcgi-starter ├── tiles │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── OpenSans │ │ │ ├── Apache License.txt │ │ │ ├── OpenSans-Bold.ttf │ │ │ ├── OpenSans-Italic.ttf │ │ │ ├── OpenSans-Light.ttf │ │ │ ├── OpenSans-LightItalic.ttf │ │ │ ├── OpenSans-Regular.ttf │ │ │ └── OpenSans-Semibold.ttf │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ └── tessera.service ├── tmpfs │ ├── README.md │ └── tasks │ │ └── main.yml ├── tools │ ├── README.md │ └── tasks │ │ └── main.yml ├── unbound │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── firewall.sh │ │ ├── unbound-ip-up.d │ │ └── unbound.conf.d │ │ │ ├── caching-timeouts.conf │ │ │ ├── caching-tweaking.conf │ │ │ ├── disable-dnssec.conf │ │ │ ├── edns-buffer-size.conf │ │ │ ├── harden-glue.conf │ │ │ ├── hide-version.conf │ │ │ ├── jostle-timeout.conf │ │ │ ├── minimal-responses.conf │ │ │ ├── no-logging.conf │ │ │ ├── number-of-threads.conf │ │ │ └── root-hints.conf │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── access-control.conf │ │ ├── listen-on-all-interfaces.conf │ │ └── remote-control.conf ├── website │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── config.json │ │ └── htaccess │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ ├── php-fcgi-starter │ │ ├── update-jekyll.sh │ │ └── webhook.php ├── wiki │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── files │ │ ├── favicon.ico │ │ ├── gitconfig │ │ └── robots.txt │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ ├── apache2.conf │ │ ├── gollum.service │ │ └── htaccess └── yanic │ ├── defaults │ └── main.yml │ ├── handlers │ └── main.yml │ ├── meta │ └── main.yml │ ├── tasks │ └── main.yml │ └── templates │ ├── config.toml │ ├── yanic-publish-ssh-master.service │ ├── yanic-publish.service │ ├── yanic-publish.timer │ └── yanic.service ├── scripts ├── open.sh └── resign.sh ├── vagrant ├── .gitignore └── Vagrantfile └── vault_passphrase.gpg /.ansible-lint: -------------------------------------------------------------------------------- 1 | skip_list: 2 | - metadata 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.orig 3 | *.retry 4 | playbooks/credentials/ 5 | host_vars/* 6 | !host_vars/*.gpg 7 | # build products... 8 | *.py[co] 9 | .vault_password 10 | /pythonenv/ 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "site"] 2 | path = site 3 | url = https://github.com/FreifunkBremen/gluon-site-ffhb.git 4 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | 3 | inventory = ./hosts 4 | roles_path = ./roles 5 | filter_plugins = ./filter_plugins 6 | library = ./library 7 | remote_user = root 8 | nocows = 1 9 | gathering = smart 10 | ansible_managed = Ansible managed 11 | vault_password_file = ./scripts/open.sh 12 | 13 | [ssh_connection] 14 | pipelining = true 15 | -------------------------------------------------------------------------------- /behave/README.md: -------------------------------------------------------------------------------- 1 | Webserver Tests With Python Behave 2 | ================================== 3 | 4 | Installation 5 | ------------ 6 | * virtualenv env 7 | * source env/bin/activate 8 | * pip install behave mechanize 9 | 10 | 11 | Running 12 | ------- 13 | * source env/bin/activate 14 | * behave 15 | -------------------------------------------------------------------------------- /behave/steps/steps_webserver.py: -------------------------------------------------------------------------------- 1 | 2 | from behave import * 3 | import mechanize 4 | import re 5 | 6 | def escape_special_chars(s): 7 | return re.sub(r"([^a-zA-Z0-9_-])", lambda m: "\\%02X" % ord(m.group(1)), s) 8 | 9 | @when(u"I access {url} as {user}/{password}") 10 | def step_impl(context, url, user, password): 11 | br = mechanize.Browser() 12 | br.add_password(url, user, password) 13 | step_impl_download(context, url, br) 14 | 15 | @when(u"I access {url}") 16 | def step_impl_download(context, url, br=None): 17 | if br is None: 18 | br = mechanize.Browser() 19 | br.set_handle_robots(False) 20 | try: 21 | fp = br.open(url) 22 | except Exception, e: 23 | fp = e 24 | 25 | context.http_status_code = fp.code 26 | context.current_url = br.geturl() 27 | context.page_source = fp.read().decode("utf-8") 28 | 29 | @then(u'the page will contain "{text}"') 30 | @then(u"the page will contain '{text}'") 31 | def step_impl(context, text): 32 | print(context.page_source) 33 | assert context.page_source.find(text) >= 0, "page source (%d bytes) didn't contain text '%s'" % (len(context.page_source), text) 34 | 35 | @then(u'the page content will be "{text}"') 36 | @then(u'the page content will be \'{text}\'') 37 | def step_impl(context, text): 38 | text = text.replace("\\n", "\n") 39 | print("expected: " + escape_special_chars(text)) 40 | print("received: " + escape_special_chars(context.page_source)) 41 | assert context.page_source == text, "page source (%d bytes) was not '%s'" % (len(context.page_source), text) 42 | 43 | @then(u'the status code will be {http_status_code}') 44 | def step_impl(context, http_status_code): 45 | assert context.http_status_code == int(http_status_code), "HTTP code is '%d' but should be '%s'" % (context.http_status_code, http_status_code) 46 | 47 | @then(u'the page URL will be "{url}"') 48 | def step_impl(context, url): 49 | assert context.current_url == url, "current URL is '%s' but should be '%s'" % (context.current_url, url) 50 | -------------------------------------------------------------------------------- /filter_plugins/derive_mac_addr.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def ntuples(lst, n): 4 | return zip(*[lst[i::n] for i in range(n)]) 5 | 6 | class FilterModule(object): 7 | def filters(self): 8 | return { 9 | "derive_mac_addr": self.derive_mac_addr 10 | } 11 | 12 | def derive_mac_addr(self, original, offset): 13 | if not re.match('^(([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}|([0-9a-fA-F]{4}\.){2}[0-9a-fA-F]{4})$', original): 14 | raise Exception("Not a MAC address: %s" % original) 15 | 16 | splitbytes = [int("".join(x), 16) for x in ntuples(re.sub('[^0-9a-fA-F]', '', original), 2)] 17 | splitbytes[0] |= 2 18 | splitbytes[-1] += offset 19 | return ':'.join('%02x' % x for x in splitbytes) 20 | 21 | if __name__ == '__main__': 22 | instance = FilterModule() 23 | for orig in ('00:00:00:00:00:00', '02:00:00:00:00:00', '0000.0000.0000'): 24 | derived = instance.derive_mac_addr(orig, 2) 25 | assert derived == '02:00:00:00:00:02', derived 26 | -------------------------------------------------------------------------------- /filter_plugins/remove_filter.py: -------------------------------------------------------------------------------- 1 | # removes an element from a list 2 | class FilterModule (object): 3 | def filters(self): 4 | return { 5 | "remove": self.remove, 6 | } 7 | 8 | def remove(self, l, e): 9 | if e in l: 10 | l.remove(e) 11 | return l 12 | -------------------------------------------------------------------------------- /filter_plugins/resolve_filter.py: -------------------------------------------------------------------------------- 1 | # Install dependencies: 2 | # apt-get install python-dnspython 3 | import dns.resolver 4 | 5 | class FilterModule (object): 6 | def filters(self): 7 | return { 8 | "resolve": self.resolve, 9 | } 10 | 11 | def resolve(self, hostname, rrtype): 12 | answers = dns.resolver.query(hostname, rrtype) 13 | for data in answers: 14 | return data.address 15 | 16 | raise errors.AnsibleFilterError('unable to get %s record for: %s' % (rrtype, hostname)) 17 | -------------------------------------------------------------------------------- /group_vars/all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pgp_keyserver: 'pool.sks-keyservers.net' 3 | site_git_root: 'https://github.com/FreifunkBremen' 4 | site_city: 'bremen' 5 | site_domain: 'bremen.freifunk.net' 6 | site_vpn_prefix: 'vpn' 7 | icvpn_as: 65196 8 | fastd_peers_limit: 200 9 | -------------------------------------------------------------------------------- /group_vars/dnsserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dns_domain_freifunk_net: bremen.freifunk.net 3 | -------------------------------------------------------------------------------- /group_vars/eventsserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | main_domain: events.bremen.freifunk.net 3 | alt_domain: events.ffhb.de 4 | 5 | respondd_vpn: false 6 | caddy_email: "geno+ffhb@fireorbit.de" 7 | 8 | meshviewer_domain: '{{ main_domain }}' 9 | meshviewer_git_root: https://github.com/FreifunkBremen/meshviewer-ffrgb.git 10 | meshviewer_git_version: ffhb-events-config 11 | meshviewer_email: info@bremen.freifunk.net 12 | meshviewer_apache: false 13 | meshviewer_geojson: true 14 | 15 | yanic_nodes_state_path: /var/www/html/data/nodes.json 16 | yanic_meshviewer_path: /var/www/html/data 17 | yanic_meshviewer_nodes: /var/www/html/data/nodes_v2.json 18 | yanic_socket: 19 | - enable: true 20 | type: unix 21 | address: "/tmp/yanic-database.socket" 22 | 23 | influxdb_username: yanic 24 | influxdb_database: yanic 25 | influxdb_password: "{{ lookup('password', 'credentials/influx_yanic length=15') }}" 26 | 27 | yanic_influxdb: 28 | - enable: true 29 | host: http://localhost:8086 30 | database: "{{ influxdb_database }}" 31 | username: "{{ influxdb_username }}" 32 | password: "{{ influxdb_password }}" 33 | 34 | influxdb_admin_user: admin 35 | influxdb_admin_password: "{{ lookup('password', 'credentials/influx_admin length=15') }}" 36 | influxdb_users: 37 | - user: "{{ influxdb_username }}" 38 | pass: "{{ influxdb_password }}" 39 | - user: public 40 | pass: public 41 | influxdb_databases: 42 | - "{{ influxdb_database }}" 43 | influxdb_access: 44 | - user: "{{ influxdb_username }}" 45 | database: "{{ influxdb_database }}" 46 | access: ALL 47 | - user: public 48 | database: "{{ influxdb_database }}" 49 | access: READ 50 | 51 | grafana_caddy: true 52 | grafana_location: /grafana 53 | grafana_domain: "{{ main_domain }}" 54 | grafana_port: 8081 55 | 56 | freifunkmanager_domain: mgmt.ffhb.de 57 | freifunkmanager_email: "{{caddy_email}}" 58 | freifunkmanager_yanic_address: "/tmp/yanic-database.socket" 59 | -------------------------------------------------------------------------------- /lib/tests/site.conf: -------------------------------------------------------------------------------- 1 | { 2 | site_name = 'Freifunk Bremen', 3 | site_code = 'ffhb', 4 | 5 | prefix4 = '10.196.0.0/16', 6 | prefix6 = 'fd2f:5119:f2c::/64' 7 | } 8 | -------------------------------------------------------------------------------- /lib/tests/tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # 3 | # Requirements: 4 | # apt-get install python-unittest2 5 | # 6 | # Run with: 7 | # unit2 discover 8 | # 9 | 10 | from sys import path 11 | path.append("..") 12 | 13 | import unittest2 14 | import json 15 | import hosts 16 | 17 | class TestHosts(unittest2.TestCase): 18 | 19 | def test_starttls_true(self): 20 | 21 | inv = hosts.Inventory('site.conf', 22 | ipv6_global_network = "2a06:8782:ffbb:1337::/64", 23 | ipv6_uplink_network = "2a06:8782:ffbb::/64", 24 | ) 25 | 26 | grp = inv.group("vpnservers", 27 | dhcp=True, 28 | batman_gateway=True, 29 | ) 30 | grp.host(1, "vpn01.bremen.freifunk.net", exit="gre", ansible_ssh_port=60023) 31 | 32 | grp = inv.group("services") 33 | grp.host(10, "service.example.com") 34 | 35 | with open('hosts.json') as data_file: 36 | data = json.load(data_file) 37 | 38 | # print inv.json_dump(indent=4) 39 | 40 | self.assertEqual(data, inv.data()) 41 | -------------------------------------------------------------------------------- /library/fastd_key: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | EXAMPLES = ''' 4 | # Generates a fastd key 5 | - fastd_key: path=/etc/fastd/site/secret.conf 6 | ''' 7 | 8 | from ansible.module_utils.basic import * 9 | import os 10 | 11 | if __name__ == '__main__': 12 | module = AnsibleModule( 13 | argument_spec={ 14 | 'path': {'required': True, 'type': 'str'}, 15 | } 16 | ) 17 | 18 | path = module.params['path'] 19 | changed = False 20 | 21 | # file does not exist or is empty? 22 | if not os.path.isfile(path) or os.stat(path).st_size == 0: 23 | # create file with restrictive permissions 24 | with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, 0o600), 'w') as handle: 25 | # generate fastd secret 26 | secret = subprocess.check_output(["fastd", "--machine-readable", "--generate-key"]).strip() 27 | handle.write('secret "{}";\n'.format(secret.decode())) 28 | 29 | changed = True 30 | 31 | module.exit_json(changed=changed) 32 | -------------------------------------------------------------------------------- /playbooks/backbone.yml: -------------------------------------------------------------------------------- 1 | # Konfiguriert Batman und GRE-Tunnel für das Backbone 2 | --- 3 | - hosts: backbone:backbone_legacy 4 | roles: 5 | - backbone-gre 6 | -------------------------------------------------------------------------------- /playbooks/dnsserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dnsserver 3 | roles: 4 | - { role: etckeeper-pre, tags: [etckeeper-pre] } 5 | - { role: nsd, tags: [nsd] } 6 | - { role: etckeeper-post, tags: [etckeeper-post] } 7 | -------------------------------------------------------------------------------- /playbooks/downlinks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: downlinks 3 | vars: 4 | batman_gateway: true 5 | roles: 6 | - { role: etckeeper-pre, tags: [etckeeper-pre, always] } 7 | - { role: openssh, tags: [openssh] } 8 | - { role: non_persistent_logging, tags: [non_persistent_logging] } 9 | - { role: downlink-firewall, tags: [downlink-firewall] } 10 | - { role: batman-adv-14, tags: [batman-adv-14], when: ('backbone_legacy' in group_names) or ('downlinks_legacy' in group_names) or ('vpnservers_legacy' in group_names) } 11 | - { role: batman-adv, tags: [batman-adv], when: ('backbone_legacy' not in group_names) and ('downlinks_legacy' not in group_names) and ('vpnservers_legacy' not in group_names) } 12 | - { role: batman-adv-interface, tags: [batman-adv-interface] } 13 | - { role: main-bridge, tags: [main-bridge] } 14 | - { role: chrony, tags: [chrony] } 15 | - { role: etckeeper-post, tags: [etckeeper-post, always] } 16 | -------------------------------------------------------------------------------- /playbooks/eventsserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: eventsserver 3 | roles: 4 | - { role: etckeeper-pre, tags: [etckeeper-pre] } 5 | - { role: apt, tags: [apt] } 6 | - { role: openssh, tags: [openssh] } 7 | - { role: system, tags: [system] } 8 | - { role: tmpfs, tags: [tmpfs] } 9 | - { role: tools, tags: [tools] } 10 | - { role: motd, tags: [motd] } 11 | - { role: mesh-announce, tags: [mesh-announce] } 12 | - { role: caddy, tags: [caddy] } 13 | - { role: eventswebsite, tags: [eventswebsite] } 14 | - { role: meshviewer, tags: [meshviewer] } 15 | - { role: influxdb, tags: [influxdb] } 16 | - { role: yanic, tags: [yanic] } 17 | - { role: grafana, tags: [grafana] } 18 | - { role: freifunkmanager, tags: [freifunkmanager] } 19 | - { role: etckeeper-post, tags: [etckeeper-post] } 20 | -------------------------------------------------------------------------------- /playbooks/ffmapserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: ffmapserver 3 | vars: 4 | yanic_publisher: true 5 | yanic_respondd_interface: "bat0" 6 | yanic_webserver: false 7 | yanic_nodes_save_interval: "15s" 8 | yanic_nodes_state_path: /opt/yanic/nodes_state.json 9 | yanic_meshviewer_path: /opt/yanic 10 | yanic_meshviewer_nodes: /opt/yanic/nodes_v2.json 11 | yanic_influxdb: 12 | - enable: "true" 13 | host: http://webserver.bremen.freifunk.net:8086 14 | database: "ffhb-nodes" 15 | username: "ffhb-respondd-collector" 16 | password: "" 17 | roles: 18 | - { role: etckeeper-pre, tags: [etckeeper-pre] } 19 | - { role: yanic, tags: [yanic] } 20 | - { role: etckeeper-post, tags: [etckeeper-post] } 21 | -------------------------------------------------------------------------------- /playbooks/standardserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: standardserver 3 | roles: 4 | - { role: etckeeper-pre, tags: [etckeeper-pre, always] } 5 | - { role: apt, tags: [apt] } 6 | - { role: nullmailer, tags: [nullmailer] } 7 | - { role: openssh, tags: [openssh] } 8 | - { role: fail2ban, tags: [fail2ban] } 9 | - { role: system, tags: [system] } 10 | - { role: tmpfs, tags: [tmpfs] } 11 | - { role: tools, tags: [tools] } 12 | - { role: motd, tags: [motd] } 13 | - { role: rkhunter, tags: [rkhunter] } 14 | - { role: etckeeper, tags: [etckeeper] } 15 | - { role: monitoring-client, tags: [monitoring-client] } 16 | - { role: etckeeper-post, tags: [etckeeper-post, always] } 17 | -------------------------------------------------------------------------------- /playbooks/vpnserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: vpnservers:vpnservers_legacy 3 | vars: 4 | batman_gateway: true 5 | roles: 6 | - { role: etckeeper-pre, tags: [etckeeper-pre, always] } 7 | - { role: tmpfs, tags: [tmpfs] } 8 | - { role: openssh, tags: [openssh] } 9 | - { role: non_persistent_logging, tags: [non_persistent_logging] } 10 | - { role: batman-adv-14, tags: [batman-adv-14], when: ('backbone_legacy' in group_names) or ('downlinks_legacy' in group_names) or ('vpnservers_legacy' in group_names) } 11 | - { role: batman-adv, tags: [batman-adv], when: ('backbone_legacy' not in group_names) and ('downlinks_legacy' not in group_names) and ('vpnservers_legacy' not in group_names) } 12 | - { role: batman-adv-interface, tags: [batman-adv-interface] } 13 | - { role: main-bridge, tags: [main-bridge] } 14 | - { role: fastd, tags: [fastd] } 15 | - { role: mesh-announce, tags: [mesh-announce] } 16 | - { role: exit-ipv4, tags: [exit-ipv4] } 17 | - { role: exit-ipv6, tags: [exit-ipv6] } 18 | - { role: chrony, tags: [chrony] } 19 | - { role: unbound, tags: [unbound] } 20 | - { role: dnsmasq, tags: [dnsmasq] } 21 | - { role: nginx, tags: [nginx] } 22 | - { role: speedtest, tags: [speedtest] } 23 | - { role: etckeeper-post, tags: [etckeeper-post, always] } 24 | -------------------------------------------------------------------------------- /playbooks/webserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: webserver 3 | vars: 4 | main_domain: bremen.freifunk.net 5 | alt_domain: ffhb.de 6 | roles: 7 | - { role: etckeeper-pre, tags: [etckeeper-pre] } 8 | - { role: chrony, tags: [chrony] } 9 | - { role: letsencrypt, tags: [letsencrypt] } 10 | - { role: apache, tags: [apache] } 11 | - { role: gatemon, tags: [gatemon] } 12 | - { role: nodemon, tags: [nodemon] } 13 | - { role: website, tags: [website] } 14 | - { role: downloadsite, tags: [downloadsite] } 15 | - { role: wiki, tags: [wiki] } 16 | - { role: tiles, tags: [tiles] } 17 | - { role: influxdb, tags: [influxdb] } 18 | - { role: grafana, tags: [grafana] } 19 | - { role: meshviewer, tags: [meshviewer] } 20 | - { role: restic, tags: [restic] } 21 | - { role: tasksite, tags: [tasksite] } 22 | - { role: etckeeper-post, tags: [etckeeper-post] } 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==4.7.0 2 | ansible-core==2.11.6 3 | cffi==1.15.0 4 | cryptography==35.0.0 5 | dnspython==2.1.0 6 | Jinja2==3.0.2 7 | MarkupSafe==2.0.1 8 | netaddr==0.8.0 9 | packaging==21.0 10 | pycparser==2.20 11 | pyparsing==2.4.7 12 | PyYAML==6.0 13 | resolvelib==0.5.4 14 | six==1.16.0 15 | -------------------------------------------------------------------------------- /roles/apache/README.md: -------------------------------------------------------------------------------- 1 | apache 2 | ========================= 3 | 4 | Installs Apache webserver 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - apache 13 | 14 | License 15 | ------------------------- 16 | 17 | GPLv3 18 | -------------------------------------------------------------------------------- /roles/apache/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apache_redirect_target: 'bremen.freifunk.net' 3 | apache_ssl_host: 'bremen.freifunk.net' 4 | -------------------------------------------------------------------------------- /roles/apache/files/anon-logs.conf: -------------------------------------------------------------------------------- 1 | LogFormat "%v:%p 127.0.0.1 - - %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined 2 | LogFormat "127.0.0.1 - - %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined 3 | LogFormat "127.0.0.1 - - %t \"%r\" %>s %O" common 4 | -------------------------------------------------------------------------------- /roles/apache/files/default-dir-options.conf: -------------------------------------------------------------------------------- 1 | 2 | Options -Indexes +FollowSymLinks -ExecCGI 3 | AllowOverride None 4 | Require all granted 5 | 6 | 7 | # disallow access to all directories and files starting with a dot: 8 | 9 | Require all denied 10 | 11 | 12 | Require all denied 13 | 14 | -------------------------------------------------------------------------------- /roles/apache/files/deflate-more-types.conf: -------------------------------------------------------------------------------- 1 | # apply GZip compression to some more file types: 2 | AddOutputFilterByType DEFLATE image/svg+xml 3 | -------------------------------------------------------------------------------- /roles/apache/files/logrotate-apache2-user: -------------------------------------------------------------------------------- 1 | /var/log/apache2/*/*.log { 2 | daily 3 | missingok 4 | rotate 14 5 | compress 6 | delaycompress 7 | notifempty 8 | create 644 root adm 9 | sharedscripts 10 | postrotate 11 | if /etc/init.d/apache2 status > /dev/null ; then \ 12 | /etc/init.d/apache2 reload > /dev/null; \ 13 | fi; 14 | endscript 15 | prerotate 16 | if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ 17 | run-parts /etc/logrotate.d/httpd-prerotate; \ 18 | fi; 19 | endscript 20 | } 21 | -------------------------------------------------------------------------------- /roles/apache/files/ocsp-stapling.conf: -------------------------------------------------------------------------------- 1 | 2 | SSLUseStapling on 3 | SSLStaplingCache shmcb:${APACHE_RUN_DIR}/stapling-cache(150000) 4 | SSLStaplingReturnResponderErrors off 5 | 6 | -------------------------------------------------------------------------------- /roles/apache/files/proxy.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | # If you want to use apache2 as a forward proxy, uncomment the 4 | # 'ProxyRequests On' line and the block below. 5 | # WARNING: Be careful to restrict access inside the block. 6 | # Open proxy servers are dangerous both to your network and to the 7 | # Internet at large. 8 | # 9 | # If you only want to use apache2 as a reverse proxy/gateway in 10 | # front of some web application server, you DON'T need 11 | # 'ProxyRequests On'. 12 | 13 | #ProxyRequests On 14 | # 15 | # AddDefaultCharset off 16 | # Require all denied 17 | # #Require local 18 | # 19 | 20 | # Enable/disable the handling of HTTP/1.1 "Via:" headers. 21 | # ("Full" adds the server version; "Block" removes all outgoing Via: headers) 22 | # Set to one of: Off | On | Full | Block 23 | #ProxyVia Off 24 | 25 | ProxyPreserveHost On 26 | 27 | 28 | 29 | # vim: syntax=apache ts=4 sw=4 sts=4 sr noet 30 | -------------------------------------------------------------------------------- /roles/apache/files/user-php-exec.conf: -------------------------------------------------------------------------------- 1 | # 1) enable FastCGI scripts (with mod_fcgid) 2 | 3 | SetHandler fcgid-script 4 | 5 | 6 | Action application/x-httpd-php /fcgi-bin/php-fcgi-starter 7 | AddHandler application/x-httpd-php .php 8 | 9 | # Direkten Zugriff auf /fcgi-bin/php-fcgi-starter verbieten; 10 | # es duerfen nur Zugriffe ueber einen Action Handler laufen, 11 | # der dann REDIRECT_HANDLER setzt. 12 | RewriteCond %{ENV:REDIRECT_HANDLER} ="" 13 | RewriteRule ^/fcgi-bin/php-fcgi-starter - [F,L] 14 | 15 | # PHP-Scripts 16 | RewriteCond %{ENV:REDIRECT_HTTPS} =on 17 | RewriteRule .* - [E=HTTPS:on] 18 | -------------------------------------------------------------------------------- /roles/apache/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart apache 3 | service: 4 | name: apache2 5 | state: restarted 6 | enabled: yes 7 | - name: reload apache 8 | service: 9 | name: apache2 10 | state: reloaded 11 | enabled: yes 12 | -------------------------------------------------------------------------------- /roles/apache/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - jessie 7 | -------------------------------------------------------------------------------- /roles/apache/templates/000-default.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | RewriteEngine on 5 | RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R,L,NE] 6 | 7 | 8 | 9 | DocumentRoot /var/www/html 10 | Redirect 307 "/" "https://{{apache_redirect_target}}/" 11 | 12 | SSLEngine on 13 | SSLCertificateFile /etc/ssl/certs/{{apache_ssl_host}}.pem 14 | SSLCertificateKeyFile /etc/ssl/private/{{apache_ssl_host}}.key 15 | 16 | -------------------------------------------------------------------------------- /roles/apt/README.md: -------------------------------------------------------------------------------- 1 | apt 2 | ========================= 3 | 4 | Configures APT 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - apt 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/apt/files/apt-periodic.conf: -------------------------------------------------------------------------------- 1 | APT::Periodic { 2 | Enable "1"; 3 | Update-Package-Lists "1"; 4 | Download-Upgradeable-Packages "1"; 5 | Unattended-Upgrade "1"; 6 | AutocleanInterval "7"; 7 | } 8 | -------------------------------------------------------------------------------- /roles/apt/files/apt-recommends.conf: -------------------------------------------------------------------------------- 1 | APT::Install-Recommends "false"; 2 | -------------------------------------------------------------------------------- /roles/apt/files/unattended-upgrades-dpkg.conf: -------------------------------------------------------------------------------- 1 | Dpkg::Options { 2 | "--force-confdef"; 3 | "--force-confold"; 4 | } 5 | -------------------------------------------------------------------------------- /roles/automysqlbackup/README.md: -------------------------------------------------------------------------------- 1 | automysqlbackup 2 | ========================= 3 | 4 | Installs backup toolsuite for MySQL 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - automysqlbackup 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/automysqlbackup/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - mysql-server 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - wheezy 9 | - jessie 10 | -------------------------------------------------------------------------------- /roles/automysqlbackup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Backup for MySQL 3 | apt: 4 | name: automysqlbackup 5 | state: present 6 | -------------------------------------------------------------------------------- /roles/backbone-gre/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | batman_interface: "bat-{{ site_code }}" 3 | -------------------------------------------------------------------------------- /roles/backbone-gre/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p gre -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/backbone-gre/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ifup backbone-gre 3 | # ifup && ifdown führt verlässlich zum Absturz des Systems 4 | command: ifup backbone-vpn{{ hostvars[item].vpn_id }} 5 | with_items: '{{ backbone_peers }}' 6 | -------------------------------------------------------------------------------- /roles/backbone-gre/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/backbone-gre/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Setup GRE interfaces 3 | template: 4 | src: interfaces 5 | dest: /etc/network/interfaces.d/backbone 6 | mode: 0644 7 | owner: root 8 | group: root 9 | notify: 10 | - ifup backbone-gre 11 | 12 | - name: Open firewall 13 | copy: 14 | src: firewall.sh 15 | dest: "{{ firewall_path }}/10-allow-gre" 16 | mode: 0644 17 | owner: root 18 | group: root 19 | when: firewall_enabled 20 | notify: reload firewall 21 | -------------------------------------------------------------------------------- /roles/backbone-gre/templates/interfaces: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | {% for host in backbone_peers %} 4 | {% set ifname = "backbone-vpn%d" % hostvars[host].vpn_id %} 5 | # {{ host }} 6 | auto {{ ifname }} 7 | iface {{ ifname }} inet manual 8 | pre-up ip link add $IFACE type gretap local {{ ansible_default_ipv4.address }} remote {{ host | resolve('a') }} ttl 64 9 | post-down ip link del $IFACE 10 | up ip link set up $IFACE 11 | down ip link set down $IFACE 12 | up ip link set $IFACE mtu {{ [ hostvars[host].max_mtu, max_mtu ] | min }} 13 | up batctl meshif {{ batman_interface }} interface add $IFACE 14 | down batctl meshif {{ batman_interface }} interface del $IFACE 15 | 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /roles/backbone-gre/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Other backbone hosts (not myself) 3 | backbone_peers: "{{ (('backbone' in group_names) or ('vpnservers' in group_names)) | ternary(groups['backbone'], groups['backbone_legacy']) | remove(inventory_hostname) }}" 4 | -------------------------------------------------------------------------------- /roles/batman-adv-14/README.md: -------------------------------------------------------------------------------- 1 | batman-adv-14 2 | ========================= 3 | 4 | Install batman-adv compat 14 from universe-factory repo 5 | 6 | 7 | Role Variables 8 | ------------------------- 9 | 10 | pgp_keyserver: keyserver for retreiving the repository key (default: 'pgp.surfnet.nl') 11 | batman-adv-14_repository: (default: 'https://repo.universe-factory.net/debian sid main') 12 | batman-adv-14_repository_key: (default: '6664E7BDA6B669881EC52E7516EF3F64CB201D9C') 13 | batman-adv-14_pkg_name: (default: 'batman-adv-dkms') 14 | 15 | 16 | Usage 17 | ------------------------- 18 | 19 | - hosts: servers 20 | roles: 21 | - batman-adv-14 22 | 23 | 24 | License 25 | ------------------------- 26 | 27 | GPLv3 28 | -------------------------------------------------------------------------------- /roles/batman-adv-14/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | batman_adv_14_apt_repository: 'https://repo.universe-factory.net/debian/ sid main' 3 | batman_adv_14_repository: 'https://github.com/freifunk-gluon/batman-adv-legacy' 4 | batman_adv_14_git_commit: '90b4d1511cd7bd3e0802412ca6d1b90e964d8691' 5 | -------------------------------------------------------------------------------- /roles/batman-adv-14/files/dkms-batman-adv-downgrade: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # We're passed the version of the kernel being installed 4 | inst_kern=$1 5 | pkg_name=batman-adv-legacy 6 | pkg_ver=2013.4.0 7 | module_name=$pkg_name 8 | 9 | uname_s=$(uname -s) 10 | 11 | _get_kernel_dir() { 12 | KVER=$1 13 | case ${uname_s} in 14 | Linux) DIR="/lib/modules/$KVER/build" ;; 15 | GNU/kFreeBSD) DIR="/usr/src/kfreebsd-headers-$KVER/sys" ;; 16 | esac 17 | echo $DIR 18 | } 19 | 20 | _check_kernel_dir() { 21 | DIR=$(_get_kernel_dir $1) 22 | case ${uname_s} in 23 | Linux) test -e $DIR/include ;; 24 | GNU/kFreeBSD) test -e $DIR/kern && test -e $DIR/conf/kmod.mk ;; 25 | *) return 1 ;; 26 | esac 27 | return $? 28 | } 29 | 30 | case "${uname_s}" in 31 | Linux) 32 | header_pkg="linux-headers-$inst_kern" 33 | kernel="Linux" 34 | ;; 35 | GNU/kFreeBSD) 36 | header_pkg="kfreebsd-headers-$inst_kern" 37 | kernel="kFreeBSD" 38 | ;; 39 | esac 40 | 41 | if dkms status -m $pkg_name -v $pkg_ver -k $inst_kern | grep -q ' installed$'; then 42 | echo "$pkg_name in version $pkg_ver already installed." >&2 43 | else 44 | dkms remove -m $pkg_name -v $pkg_ver -k $inst_kern || true 45 | dkms build -m $pkg_name -v $pkg_ver -k $inst_kern 46 | dkms install -m $pkg_name -v $pkg_ver --force -k $inst_kern 47 | fi 48 | 49 | if ! _check_kernel_dir $inst_kern ; then 50 | echo "dkms: WARNING: $kernel headers are missing, which may explain the above failures." >&2 51 | echo " please install the $header_pkg package to fix this." >&2 52 | fi 53 | -------------------------------------------------------------------------------- /roles/batman-adv-14/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for batman-adv-14 3 | - name: Remove old repository 4 | apt_repository: 5 | repo: "deb {{ batman_adv_14_apt_repository }}" 6 | state: absent 7 | 8 | - name: Remove old dkms package 9 | apt: 10 | name: batman-adv-dkms 11 | state: absent 12 | purge: yes 13 | 14 | - name: Install batman-adv dependencies 15 | apt: 16 | name: 17 | - dkms 18 | - lsof 19 | - linux-headers-amd64 20 | 21 | - name: Clone batman-adv repo 22 | git: 23 | repo: "{{ batman_adv_14_repository }}" 24 | dest: "/usr/src/batman-adv-legacy-2013.4.0" 25 | version: "{{ batman_adv_14_git_commit }}" 26 | 27 | - name: Add repo to dkms 28 | command: dkms add -m batman-adv-legacy -v 2013.4.0 29 | args: 30 | creates: /var/lib/dkms/batman-adv-legacy/2013.4.0/source/Makefile 31 | 32 | - name: Copy kernel postinst downgrade hook 33 | copy: 34 | src: dkms-batman-adv-downgrade 35 | dest: /etc/kernel/postinst.d/00dkms-batman-adv-downgrade 36 | mode: 0755 37 | 38 | - name: Ensure correct version was installed 39 | shell: /etc/kernel/postinst.d/00dkms-batman-adv-downgrade $(uname -r) 40 | register: batman_adv_version_result 41 | changed_when: '"already installed" not in batman_adv_version_result.stderr' 42 | 43 | - name: Enable batman during boot 44 | lineinfile: 45 | path: /etc/modules 46 | line: batman-adv 47 | 48 | - name: Load batman-adv module 49 | modprobe: 50 | name: batman-adv 51 | -------------------------------------------------------------------------------- /roles/batman-adv-interface/README.md: -------------------------------------------------------------------------------- 1 | batman-adv-interface 2 | ========================= 3 | 4 | Install the batman interface 5 | 6 | 7 | Role Variables 8 | ------------------------- 9 | 10 | batman_interface: Interface on which works Batman (default: 'bat-{{ site_code }}' ) 11 | 12 | 13 | Usage 14 | ------------------------- 15 | 16 | - hosts: servers 17 | vars: 18 | site_code: ffhb 19 | roles: 20 | - batman-adv-interface 21 | 22 | 23 | License 24 | ------------------------- 25 | 26 | GPLv3 27 | -------------------------------------------------------------------------------- /roles/batman-adv-interface/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | batman_interface: bat-{{ site_code }} 3 | batman_dummy_interface: 'bat-{{ site_code }}-dummy' 4 | batman_hop_penalty: 96 5 | batman_gateway: false 6 | -------------------------------------------------------------------------------- /roles/batman-adv-interface/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install bridge-utils 3 | apt: 4 | name: bridge-utils 5 | 6 | - name: Install old networking tools 7 | apt: 8 | name: net-tools 9 | 10 | - name: Install batctl 11 | apt: 12 | name: batctl 13 | 14 | - name: Install batman pre-up script 15 | copy: 16 | src: if-pre-up 17 | dest: /etc/network/if-pre-up.d/batadv 18 | mode: 0755 19 | when: (ansible_distribution == "Debian" and (ansible_distribution_version is version_compare("11", ">="))) 20 | 21 | - name: Install batman pre-up script 22 | copy: 23 | src: if-pre-up-legacy 24 | dest: /etc/network/if-pre-up.d/batadv 25 | mode: 0755 26 | when: (ansible_distribution == "Debian" and (ansible_distribution_version is version_compare("11", "<"))) 27 | 28 | - name: Install interfaces file 29 | template: 30 | src: interfaces 31 | dest: /etc/network/interfaces.d/{{ batman_interface }} 32 | mode: 0644 33 | owner: root 34 | group: root 35 | 36 | - name: Set interfaces up 37 | command: ifup {{ item }} 38 | register: ifup_result 39 | changed_when: '"already configured" not in ifup_result.stderr' 40 | with_items: 41 | - "{{ batman_dummy_interface }}" 42 | - "{{ batman_interface }}" 43 | -------------------------------------------------------------------------------- /roles/batman-adv-interface/templates/interfaces: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | auto {{ batman_dummy_interface }} 4 | iface {{ batman_dummy_interface }} inet manual 5 | pre-up ip link add name $IFACE type dummy 6 | up ip link set $IFACE up 7 | down ip link set $IFACE down 8 | post-down ip link del $IFACE 9 | 10 | auto {{ batman_interface }} 11 | iface {{ batman_interface }} inet manual 12 | batadv-ports {{ batman_dummy_interface }} 13 | {% if ansible_default_ipv6.macaddress is defined %} 14 | batadv-hw {{ ansible_default_ipv6.macaddress | derive_mac_addr(2) }} 15 | {% else %} 16 | batadv-hw {{ ansible_default_ipv4.macaddress | derive_mac_addr(2) }} 17 | {% endif %} 18 | batadv-hop-penalty {{ batman_hop_penalty }} 19 | {% if batman_gateway %} 20 | batadv-gw-mode server 21 | batadv-gw-bandwidth 100Mbit/100Mbit 22 | {% endif %} 23 | batadv-orig-interval 5000 24 | # set interface up 25 | up ip link set $IFACE up 26 | down ip link set $IFACE down 27 | -------------------------------------------------------------------------------- /roles/batman-adv/README.md: -------------------------------------------------------------------------------- 1 | batman-adv 2 | ========================= 3 | 4 | Install batman-adv 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - batman-adv 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/batman-adv/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: kaleng 4 | categories: 5 | - networking 6 | description: "install batman-adv" 7 | license: GPLv3 8 | min_ansible_version: 1.6 9 | platforms: 10 | - name: Debian 11 | versions: 12 | - wheezy 13 | - jessie 14 | -------------------------------------------------------------------------------- /roles/batman-adv/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for batman-adv 3 | - name: Enable batman during boot 4 | lineinfile: 5 | path: /etc/modules 6 | line: batman-adv 7 | 8 | - name: Load batman-adv module 9 | modprobe: 10 | name: batman-adv 11 | -------------------------------------------------------------------------------- /roles/caddy/README.md: -------------------------------------------------------------------------------- 1 | # caddy 2 | 3 | ## Bugfix 4 | Caddy need the current version of systemd (or without user change) 5 | 6 | ``` 7 | deb http://httpredir.debian.org/debian jessie-backports main contrib non-free 8 | ``` 9 | 10 | ``` 11 | apt update 12 | apt install systemd -t jessie-backports 13 | apt upgrade -t jessie-backports 14 | ``` 15 | -------------------------------------------------------------------------------- /roles/caddy/files/caddy.service.patch: -------------------------------------------------------------------------------- 1 | --- caddy.service 2016-09-28 21:07:57.000000000 +0200 2 | +++ caddy 2016-12-07 12:42:54.304716833 +0100 3 | @@ -17,7 +17,7 @@ Group=www-data 4 | Environment=CADDYPATH=/etc/ssl/caddy 5 | 6 | ; Always set "-root" to something safe in case it gets forgotten in the Caddyfile. 7 | -ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp 8 | +ExecStart=/opt/go/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp 9 | ExecReload=/bin/kill -USR1 $MAINPID 10 | 11 | ; Limit the number of file descriptors; see `man systemd.exec` for more limit settings. 12 | @@ -38,9 +38,9 @@ ReadWriteDirectories=/etc/ssl/caddy 13 | ; The following additional security directives only work with systemd v229 or later. 14 | ; They further retrict privileges that can be gained by caddy. Uncomment if you like. 15 | ; Note that you may have to add capabilities required by any plugins in use. 16 | -;CapabilityBoundingSet=CAP_NET_BIND_SERVICE 17 | -;AmbientCapabilities=CAP_NET_BIND_SERVICE 18 | +CapabilityBoundingSet=CAP_NET_BIND_SERVICE 19 | +AmbientCapabilities=CAP_NET_BIND_SERVICE 20 | ;NoNewPrivileges=true 21 | 22 | [Install] 23 | WantedBy=multi-user.target 24 | -------------------------------------------------------------------------------- /roles/caddy/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart caddy 3 | service: 4 | name: caddy 5 | state: restarted 6 | 7 | - name: reload systemd 8 | systemd: 9 | daemon_reload: yes 10 | -------------------------------------------------------------------------------- /roles/caddy/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - go 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - jessie 9 | -------------------------------------------------------------------------------- /roles/caddy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install tools 3 | apt: 4 | name: 5 | - patch 6 | - debian-keyring 7 | - debian-archive-keyring 8 | 9 | - name: Install caddy repo keyring 10 | apt_key: 11 | url: https://dl.cloudsmith.io/public/caddy/stable/gpg.key 12 | state: present 13 | 14 | - name: Install caddy repo 15 | apt_repository: 16 | repo: deb https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main 17 | state: present 18 | 19 | - name: Install caddy 20 | apt: 21 | name: caddy 22 | notify: 23 | - restart caddy 24 | 25 | - name: Create ssl folder 26 | file: 27 | path: /etc/ssl/caddy 28 | state: directory 29 | mode: 0750 30 | owner: www-data 31 | group: www-data 32 | 33 | - name: Create configuration folder 34 | file: 35 | path: /etc/caddy/hosts 36 | state: directory 37 | mode: 0755 38 | owner: www-data 39 | group: www-data 40 | 41 | - name: Configurate caddy 42 | template: 43 | src: Caddyfile 44 | dest: /etc/caddy/Caddyfile 45 | mode: 0644 46 | owner: www-data 47 | group: www-data 48 | notify: restart caddy 49 | 50 | - name: Create web folders 51 | file: 52 | path: /var/www/html 53 | state: directory 54 | mode: 0755 55 | owner: www-data 56 | group: www-data 57 | 58 | - name: Configurate caddy for hostname 59 | template: 60 | src: hostname.caddy 61 | dest: /etc/caddy/hosts/00-default.act 62 | mode: 0644 63 | owner: www-data 64 | group: www-data 65 | notify: restart caddy 66 | 67 | - name: Enable caddy 68 | service: 69 | name: caddy 70 | enabled: yes 71 | -------------------------------------------------------------------------------- /roles/caddy/templates/Caddyfile: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | import ./hosts/*.act 4 | -------------------------------------------------------------------------------- /roles/caddy/templates/hostname.caddy: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | http://{{main_domain}}, http://{{alt_domain}} { 3 | redir https://{{main_domain}}{uri} 4 | } 5 | 6 | https://{{main_domain}}, https://{{alt_domain}} { 7 | tls {{caddy_email}} 8 | gzip 9 | index index.html 10 | root /var/www/html 11 | header / { 12 | Access-Control-Allow-Origin * 13 | Access-Control-Allow-Methods "GET, POST, OPTIONS" 14 | -Server 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /roles/chrony/README.md: -------------------------------------------------------------------------------- 1 | chrony 2 | ========================= 3 | 4 | Install NTP server 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - chrony 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/chrony/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart chrony 3 | service: 4 | name: chrony 5 | state: restarted 6 | -------------------------------------------------------------------------------- /roles/chrony/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/chrony/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install chrony 3 | apt: 4 | name: chrony 5 | 6 | - name: Install configuration 7 | template: 8 | src: chrony.conf 9 | dest: /etc/chrony/chrony.conf 10 | mode: 0644 11 | owner: root 12 | group: root 13 | notify: restart chrony 14 | when: "'vpnservers' in group_names" 15 | 16 | - name: Open firewall for NTP 17 | template: 18 | src: firewall.sh 19 | dest: "{{ firewall_path }}/30-chrony" 20 | mode: 0644 21 | owner: root 22 | group: root 23 | notify: reload firewall 24 | when: "firewall_enabled and 'vpnservers' in group_names" 25 | 26 | - name: Autostart chrony 27 | service: 28 | name: chrony 29 | enabled: yes 30 | -------------------------------------------------------------------------------- /roles/chrony/templates/chrony.conf: -------------------------------------------------------------------------------- 1 | # Welcome to the chrony configuration file. See chrony.conf(5) for more 2 | # information about usuable directives. 3 | server 0.debian.pool.ntp.org minpoll 8 4 | server 1.debian.pool.ntp.org minpoll 8 5 | server 2.debian.pool.ntp.org minpoll 8 6 | server 3.debian.pool.ntp.org minpoll 8 7 | 8 | 9 | # This directive specify the location of the file containing ID/key pairs for 10 | # NTP authentication. 11 | keyfile /etc/chrony/chrony.keys 12 | 13 | # This directive specify the file into which chronyd will store the rate 14 | # information. 15 | driftfile /var/lib/chrony/chrony.drift 16 | 17 | # Uncomment the following line to turn logging on. 18 | #log tracking measurements statistics 19 | 20 | # Log files location. 21 | logdir /var/log/chrony 22 | 23 | # Stop bad estimates upsetting machine clock. 24 | maxupdateskew 100.0 25 | 26 | # Allow computers on the unrouted nets to use the server. 27 | 28 | allow {{ ipv4_network }} 29 | allow {{ ipv6_local_network }} 30 | {% if ipv6_global_network %} 31 | allow {{ ipv6_global_network }} 32 | {% endif %} 33 | 34 | # This directive tells 'chronyd' to parse the 'adjtime' file to find out if the 35 | # real-time clock keeps local time or UTC. It overrides the 'rtconutc' directive. 36 | hwclockfile /etc/adjtime 37 | 38 | # This directive enables kernel synchronisation (every 11 minutes) of the 39 | # real-time clock. Note that it can’t be used along with the 'rtcfile' directive. 40 | rtcsync 41 | 42 | # Step the system clock instead of slewing it if the adjustment is larger than 43 | # one second, but only in the first three clock updates. 44 | makestep 1 3 45 | -------------------------------------------------------------------------------- /roles/chrony/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -i '{{ main_bridge }}' -p udp --dport 123 -j ACCEPT 2 | ipt6 -A INPUT -i '{{ main_bridge }}' -p udp --dport 123 -j ACCEPT 3 | -------------------------------------------------------------------------------- /roles/dnsmasq/README.md: -------------------------------------------------------------------------------- 1 | dnsmasq 2 | ========================= 3 | 4 | Install and configure dnsmasq for DHCP 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - dnsmasq 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/dnsmasq/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dhcp_dns: '{{ batman_ipv4.address }}' 3 | main_bridge: 'br-{{ site_code }}' 4 | -------------------------------------------------------------------------------- /roles/dnsmasq/files/dnsmasq-hook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -eu 4 | 5 | MODE="$1" 6 | MAC="$2" 7 | IP="$3" 8 | 9 | if [ -z "${DNSMASQ_INTERFACE:-}" ]; then 10 | exit 0 11 | fi 12 | 13 | case "$MODE" in 14 | add|old) 15 | ip neigh replace "$IP" dev "$DNSMASQ_INTERFACE" lladdr "$MAC" nud reachable 16 | ;; 17 | del) 18 | ip neigh delete "$IP" dev "$DNSMASQ_INTERFACE" 19 | conntrack -D -s "$IP" > /dev/null 20 | ;; 21 | esac 22 | -------------------------------------------------------------------------------- /roles/dnsmasq/files/dnsmasq-tmpfs.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Persist DHCP leases file to disk 3 | ConditionFileNotEmpty=/tmp/dnsmasq.leases 4 | 5 | [Service] 6 | ExecStart=/bin/cp /tmp/dnsmasq.leases /var/lib/misc/dnsmasq.leases 7 | -------------------------------------------------------------------------------- /roles/dnsmasq/files/dnsmasq-tmpfs.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Regularly persist DHCP leases file to disk 3 | 4 | [Timer] 5 | OnCalendar=hourly 6 | RandomizedDelaySec=1h 7 | FixedRandomDelay=yes 8 | 9 | [Install] 10 | WantedBy=timers.target 11 | -------------------------------------------------------------------------------- /roles/dnsmasq/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload systemd 3 | systemd: 4 | daemon_reload: yes 5 | 6 | - name: restart dnsmasq 7 | service: 8 | name: dnsmasq 9 | state: restarted 10 | -------------------------------------------------------------------------------- /roles/dnsmasq/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/dnsmasq/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install dnsmasq 3 | apt: 4 | name: 5 | - dnsmasq 6 | - conntrack # for clearing connections on lease expiration 7 | 8 | - name: Create dropin folder for systemd 9 | file: 10 | path: /etc/systemd/system/dnsmasq.service.d 11 | state: directory 12 | mode: '0755' 13 | owner: root 14 | group: root 15 | 16 | - name: Create dropin file 17 | copy: 18 | dest: /etc/systemd/system/dnsmasq.service.d/local.conf 19 | mode: '0644' 20 | owner: root 21 | group: root 22 | content: | 23 | [Service] 24 | ExecStartPre=-/bin/cp /var/lib/misc/dnsmasq.leases /tmp/dnsmasq.leases 25 | ExecStopPost=/bin/cp /tmp/dnsmasq.leases /var/lib/misc/dnsmasq.leases 26 | notify: reload systemd 27 | 28 | - name: Install timer unit to persist leases file 29 | copy: 30 | src: '{{ item }}' 31 | dest: /etc/systemd/system/ 32 | mode: 0644 33 | loop: 34 | - dnsmasq-tmpfs.service 35 | - dnsmasq-tmpfs.timer 36 | 37 | 38 | - name: Enable timer unit to persist leases file 39 | systemd: 40 | name: dnsmasq-tmpfs.timer 41 | state: started 42 | enabled: yes 43 | daemon_reload: yes 44 | 45 | - name: Remove obsolete cronjob 46 | file: 47 | path: /etc/cron.hourly/dnsmasq-tmpfs 48 | state: absent 49 | 50 | - name: Copy dnsmasq lease script 51 | copy: 52 | dest: /usr/local/sbin/dnsmasq-hook.sh 53 | src: dnsmasq-hook.sh 54 | owner: root 55 | group: root 56 | mode: '0755' 57 | 58 | - name: Configure dnsmasq 59 | template: 60 | src: dnsmasq.conf 61 | dest: /etc/dnsmasq.conf 62 | mode: 0644 63 | owner: root 64 | group: root 65 | notify: restart dnsmasq 66 | 67 | - name: Open firewall for DHCP 68 | template: 69 | src: firewall.sh 70 | dest: "{{ firewall_path }}/30-dnsmasq" 71 | mode: 0644 72 | owner: root 73 | group: root 74 | when: firewall_enabled 75 | notify: reload firewall 76 | 77 | - name: Enable dnsmasq 78 | service: 79 | name: dnsmasq 80 | enabled: yes 81 | -------------------------------------------------------------------------------- /roles/dnsmasq/templates/dnsmasq.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | log-facility=local7 4 | 5 | interface={{ main_bridge }} 6 | bind-interfaces 7 | 8 | port=0 9 | 10 | quiet-dhcp 11 | 12 | dhcp-authoritative 13 | dhcp-leasefile=/tmp/dnsmasq.leases 14 | dhcp-lease-max=2550 15 | 16 | dhcp-range=set:main,{{ dhcp.range_begin }},{{ dhcp.range_end }},{{ dhcp.netmask }},30m 17 | dhcp-option=main,option:router,{{ batman_ipv4.address }} 18 | dhcp-option=option:dns-server,{{ batman_ipv4.address }} 19 | dhcp-option=option:domain-search,{{site_domain}} 20 | 21 | no-ping 22 | dhcp-script=/usr/local/sbin/dnsmasq-hook.sh 23 | {% if 'vpnservers_legacy' not in group_names %} 24 | script-on-renewal 25 | {% endif %} 26 | -------------------------------------------------------------------------------- /roles/dnsmasq/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt4 -A INPUT -i '{{ main_bridge }}' -p udp --dport 67:68 -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/downlink-firewall/defaults/main.yml: -------------------------------------------------------------------------------- 1 | main_bridge: 'br-{{ site_code }}' 2 | -------------------------------------------------------------------------------- /roles/downlink-firewall/files/ipv6-neigh-cache-negative.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Cache negative IPv6 ND results 3 | Before=firewall.service 4 | 5 | [Service] 6 | ExecStart=/usr/local/sbin/ipv6-neigh-cache-negative.sh 7 | Restart=always 8 | RestartSec=10 9 | 10 | [Install] 11 | WantedBy=network.target -------------------------------------------------------------------------------- /roles/downlink-firewall/files/ipv6-neigh-cache-negative.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -eu 4 | 5 | # This little script listens to `ip -6 monitor neigh` and adds addresses for 6 | # which IPv6 ND lookups failed to an ipset, which in turn can be used by the 7 | # firewall to drop packets to these addresses. 8 | 9 | IPSET_NAME="ND_FAILED" 10 | IPSET_TIMEOUT=60 11 | IPSET_HASHSIZE=4096 12 | 13 | 14 | ipset -exist create "$IPSET_NAME" hash:net family inet6 hashsize "$IPSET_HASHSIZE" timeout "$IPSET_TIMEOUT" 15 | 16 | ip -6 monitor neigh | while read -r LINE; do 17 | case "$LINE" in 18 | fe80::*|"Deleted "*) 19 | continue 20 | ;; 21 | *" FAILED") 22 | printf "add -exist %s %s\nCOMMIT\n" "$IPSET_NAME" "${LINE%% *}" 23 | ;; 24 | esac 25 | done | ipset restore 26 | -------------------------------------------------------------------------------- /roles/downlink-firewall/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Reload systemd 3 | systemd: 4 | daemon_reload: yes 5 | 6 | - name: Restart ipv6-neigh-cache-negative 7 | systemd: 8 | name: ipv6-neigh-cache-negative.service 9 | state: restarted 10 | -------------------------------------------------------------------------------- /roles/downlink-firewall/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install ipv6-neigh-cache-negative.sh 3 | copy: 4 | src: ipv6-neigh-cache-negative.sh 5 | dest: /usr/local/sbin/ipv6-neigh-cache-negative.sh 6 | mode: '0755' 7 | notify: Restart ipv6-neigh-cache-negative 8 | when: firewall_enabled 9 | 10 | - name: Install ipv6-neigh-cache-negative.service 11 | copy: 12 | src: ipv6-neigh-cache-negative.service 13 | dest: /etc/systemd/system/ipv6-neigh-cache-negative.service 14 | mode: '0644' 15 | notify: 16 | - Reload systemd 17 | - Restart ipv6-neigh-cache-negative 18 | when: firewall_enabled 19 | 20 | - name: Enable ipv6-neigh-cache-negative.service 21 | systemd: 22 | daemon_reload: yes 23 | name: ipv6-neigh-cache-negative.service 24 | enabled: yes 25 | state: started 26 | when: firewall_enabled 27 | 28 | - name: Install firewall for dowlink 29 | copy: 30 | dest: /etc/firewall.d/20-downlink-forwarding 31 | content: | 32 | ipt6 -A FORWARD -m set --match-set ND_FAILED dst -j REJECT --reject-with addr-unreach 33 | ipt6 -A FORWARD -i '{{ exit_ipv6_interface }}' -o '{{ main_bridge }}' -j ACCEPT 34 | mode: 0644 35 | owner: root 36 | group: root 37 | when: firewall_enabled 38 | notify: reload firewall 39 | -------------------------------------------------------------------------------- /roles/downloadsite/README.md: -------------------------------------------------------------------------------- 1 | downloadsite 2 | ========================= 3 | 4 | Set up webserver for download site of Freifunk Bremen 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - downloadsite 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/downloadsite/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | downloads_email: 'info@bremen.freifunk.net' 3 | downloads_user: 'downloads' 4 | downloads_group: 'downloads' 5 | downloads_subdomain: 'downloads' 6 | downloads_domain: '{{ downloads_subdomain }}.{{ main_domain }}' 7 | downloads_rsync_port: 63113 8 | -------------------------------------------------------------------------------- /roles/downloadsite/files/htaccess: -------------------------------------------------------------------------------- 1 | Options +Indexes 2 | IndexOptions FancyIndexing FoldersFirst HTMLTable IconsAreLinks SuppressRules SuppressDescription XHTML 3 | HeaderName /header.html 4 | IndexStyleSheet /style.css 5 | ReadmeName footer.html 6 | IndexIgnore header.html style.css footer.html robots.txt favicon.ico 7 | AddDescription "Knotendaten für die Liste" data 8 | AddDescription "Aktuelle Firmware, s.a. Anleitung zum Flashen" firmware 9 | AddDescription "\"Freifunk verbindet!\"-Video" video 10 | AddOutputFilter DEFLATE json 11 | AddType text/plain manifest 12 | Header set Access-Control-Allow-Origin "*" 13 | -------------------------------------------------------------------------------- /roles/downloadsite/files/rsync.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=fast remote file copy program daemon 3 | 4 | [Service] 5 | ExecStart=/usr/bin/rsync --no-detach --daemon --config .config/rsyncd.conf 6 | 7 | [Install] 8 | WantedBy=default.target 9 | -------------------------------------------------------------------------------- /roles/downloadsite/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - tools 4 | - apache 5 | - letsencrypt 6 | galaxy_info: 7 | platforms: 8 | - name: Debian 9 | versions: 10 | - jessie 11 | -------------------------------------------------------------------------------- /roles/downloadsite/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ downloads_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ downloads_subdomain }}.{{ alt_domain }} 6 | 7 | ServerAdmin {{ downloads_email }} 8 | 9 | DocumentRoot /var/www/{{ downloads_user }}/domains/{{ downloads_domain }} 10 | 11 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 12 | Options +SymLinksIfOwnerMatch -Includes 13 | 14 | 15 | SSLProxyEngine on 16 | ProxyPass /opkg/openwrt/ https://downloads.openwrt.org/ 17 | ProxyPreserveHost Off 18 | 19 | ErrorLog /var/log/apache2/{{ downloads_user }}/default-error.log 20 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 21 | 22 | SSLEngine on 23 | SSLCertificateFile /etc/letsencrypt/certs/{{ downloads_domain }}/fullchain.pem 24 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ downloads_domain }}/privkey.pem 25 | 26 | 27 | ServerName {{ downloads_subdomain }}.{{ main_domain }} 28 | ServerAlias {{ downloads_subdomain }}.{{ alt_domain }} 29 | 30 | ServerAdmin {{ downloads_email }} 31 | 32 | DocumentRoot /var/www/{{ downloads_user }}/domains/{{ downloads_domain }} 33 | 34 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 35 | Options +SymLinksIfOwnerMatch -Includes 36 | 37 | 38 | ProxyPass /opkg/openwrt/ http://downloads.openwrt.org/ 39 | ProxyPreserveHost Off 40 | 41 | ErrorLog /var/log/apache2/{{ downloads_user }}/default-error.log 42 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 43 | 44 | -------------------------------------------------------------------------------- /roles/downloadsite/templates/rsyncd.conf: -------------------------------------------------------------------------------- 1 | use chroot = false 2 | port = {{ downloads_rsync_port }} 3 | pid file = /home/{{ downloads_user }}/.var/run/rsyncd.pid 4 | lock file = /home/{{ downloads_user }}/.var/run/rsyncd.lock 5 | max connections = 5 6 | 7 | [firmware] 8 | path=/var/www/{{ downloads_user }}/domains/{{ downloads_domain }}/firmware 9 | comment=Freifunk Bremen Firmware 10 | 11 | [opkg] 12 | path=/var/www/{{ downloads_user }}/domains/{{ downloads_domain }}/opkg 13 | comment=Freifunk Bremen Package Repository 14 | -------------------------------------------------------------------------------- /roles/etckeeper-post/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if etckeeper is installed 3 | stat: 4 | path: /usr/bin/etckeeper 5 | register: etckeeper_binary 6 | 7 | - block: 8 | - name: Run handlers 9 | meta: flush_handlers 10 | 11 | - name: Reenable autocommit before APT run 12 | replace: 13 | dest: /etc/etckeeper/etckeeper.conf 14 | regexp: '^([\#\s]*)?AVOID_COMMIT_BEFORE_INSTALL=[01]' 15 | replace: 'AVOID_COMMIT_BEFORE_INSTALL=1' 16 | changed_when: false 17 | 18 | - name: Get Git commit id 19 | command: git rev-parse HEAD # noqa 303 20 | register: ansible_git_commit_id 21 | delegate_to: localhost 22 | changed_when: false 23 | check_mode: false 24 | 25 | - name: Commit etckeeper 26 | command: etckeeper commit "ansible run with commit {{ ansible_git_commit_id.stdout }}" 27 | register: etckeeper_commit 28 | changed_when: "etckeeper_commit.rc == 0" 29 | failed_when: "etckeeper_commit.rc > 1" 30 | when: not ansible_git_commit_id.skipped is defined 31 | when: etckeeper_binary.stat.executable is defined and etckeeper_binary.stat.executable 32 | -------------------------------------------------------------------------------- /roles/etckeeper-pre/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if etckeeper is installed 3 | stat: 4 | path: /usr/bin/etckeeper 5 | register: etckeeper_binary 6 | 7 | - block: 8 | - name: Check if etc is committed 9 | command: git -C /etc ls-files --modified --deleted --others --exclude-standard # noqa command-instead-of-module 10 | register: ansible_etckeeper_committed 11 | changed_when: false 12 | failed_when: ansible_etckeeper_committed.stdout != "" 13 | 14 | - name: Disable autocommit before APT run 15 | replace: 16 | dest: /etc/etckeeper/etckeeper.conf 17 | regexp: '^([\#\s]*)?AVOID_COMMIT_BEFORE_INSTALL=[01]' 18 | replace: 'AVOID_COMMIT_BEFORE_INSTALL=0' 19 | changed_when: false 20 | when: etckeeper_binary.stat.executable is defined and etckeeper_binary.stat.executable 21 | -------------------------------------------------------------------------------- /roles/etckeeper/README.md: -------------------------------------------------------------------------------- 1 | etckeeper 2 | ========================= 3 | 4 | Installs etckeeper 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - etckeeper 13 | 14 | License 15 | ------------------------- 16 | 17 | GPLv3 18 | -------------------------------------------------------------------------------- /roles/etckeeper/files/git-config: -------------------------------------------------------------------------------- 1 | [user] 2 | name = ffhb root-user 3 | email = server@bremen.freifunk.net 4 | [pull] 5 | rebase = true 6 | [push] 7 | default = simple 8 | -------------------------------------------------------------------------------- /roles/etckeeper/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/etckeeper/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install etckeeper 3 | apt: 4 | name: 5 | - git 6 | - etckeeper 7 | 8 | - name: Comment all VCSs 9 | replace: 10 | dest: /etc/etckeeper/etckeeper.conf 11 | regexp: '^VCS="(?!git)' 12 | replace: '#VCS="' 13 | 14 | - name: Activate git as only VCS 15 | replace: 16 | dest: /etc/etckeeper/etckeeper.conf 17 | regexp: '^#VCS="git"' 18 | replace: 'VCS="git"' 19 | 20 | - name: Disable daily autocommit 21 | replace: 22 | dest: /etc/etckeeper/etckeeper.conf 23 | regexp: '^#AVOID_DAILY_AUTOCOMMITS=1' 24 | replace: 'AVOID_DAILY_AUTOCOMMITS=1' 25 | 26 | - name: Create git configuration directory 27 | file: 28 | path: /root/.config/git 29 | recurse: yes 30 | state: directory 31 | owner: root 32 | group: root 33 | mode: 0700 34 | 35 | - name: Copy Git configuration 36 | copy: 37 | src: git-config 38 | dest: /root/.config/git/config 39 | owner: root 40 | group: root 41 | mode: 0600 42 | force: no 43 | 44 | - name: Uninitialize repository in /etc 45 | command: /usr/bin/etckeeper uninit -f 46 | args: 47 | creates: /etc/.git 48 | 49 | - name: Initialize repository in /etc with git 50 | command: /usr/bin/etckeeper init 51 | args: 52 | creates: /etc/.git 53 | -------------------------------------------------------------------------------- /roles/eventswebsite/README.md: -------------------------------------------------------------------------------- 1 | # Eventswebsite 2 | Install a little website on a server. 3 | This website would be a index to get access to public services on a event. 4 | (Examples for such services are grafana and a meshviewer). 5 | 6 | 7 | Maybe later, replace it with a git clone of a website! 8 | -------------------------------------------------------------------------------- /roles/eventswebsite/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install index 2 | template: 3 | src: index.html 4 | dest: /var/www/html/ 5 | owner: www-data 6 | mode: 0644 7 | -------------------------------------------------------------------------------- /roles/eventswebsite/templates/index.html: -------------------------------------------------------------------------------- 1 |

Freifunk Bremen Events

2 |

This is a public accessable server for services during a events managed by Freifunk Bremen.

3 | The list of public services: 4 | 8 | -------------------------------------------------------------------------------- /roles/exit-ipv4/README.md: -------------------------------------------------------------------------------- 1 | exit-ipv4 2 | ========================= 3 | 4 | A role to setup up a OpenVPN, GRE or IPIP connection as exit. 5 | 6 | 7 | Role Variables 8 | ------------------------ 9 | 10 | ### GRE or IPIP Exit 11 | 12 | exit_ipv4: Tunnel mode (GRE or IPIP) 13 | exit_ipv4_address 14 | exit_ipv4_address_global 15 | exit_ipv4_address_peer 16 | exit_ipv4_local 17 | exit_ipv4_remote 18 | 19 | ### default (dangerous) 20 | 21 | Be aware of the german "Störerhaftung"! 22 | 23 | exit_ipv4: default 24 | 25 | 26 | Usage 27 | ------------------------ 28 | 29 | - hosts: servers 30 | roles: 31 | - { role: exit-ipv4, exit_ipv4: "gre" } 32 | 33 | 34 | License 35 | ------------------------ 36 | 37 | GPLv3 38 | -------------------------------------------------------------------------------- /roles/exit-ipv4/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exit_ipv4: "" 3 | exit_ipv4_mtu: 1400 4 | exit_ipv4_interface: vpn-uplink 5 | exit_ipv4_address_global: False 6 | ffhb_routing_table: default-freifunk 7 | main_bridge: 'br-{{ site_code }}' 8 | exit_masquerade: true 9 | ipp2p_drop: false 10 | ipp2p_protocols: 11 | - apple 12 | - ares 13 | - bit 14 | - dc 15 | - edk 16 | - gnu 17 | - kazaa 18 | - mute 19 | - soul 20 | - waste 21 | - winmx 22 | - xdcc 23 | -------------------------------------------------------------------------------- /roles/exit-ipv4/files/10-allow-gre: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p gre -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/exit-ipv4/files/10-allow-ipip: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p ipip -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/exit-ipv4/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - wheezy 9 | - jessie 10 | -------------------------------------------------------------------------------- /roles/exit-ipv4/tasks/default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure firewall for IPv4 exit 3 | template: 4 | src: "default/{{ item }}" 5 | dest: "{{ firewall_path }}/" 6 | mode: 0644 7 | owner: root 8 | group: root 9 | with_items: 10 | - 10-tcpmss-ipv4 11 | - 20-exit-ipv4 12 | when: firewall_enabled 13 | notify: reload firewall 14 | 15 | - name: Install hook 16 | template: 17 | src: default/up.sh 18 | dest: "/etc/network/if-up.d/{{ ffhb_routing_table }}" 19 | mode: 0755 20 | owner: root 21 | group: root 22 | when: exit_ipv4 == "default" 23 | 24 | - name: Remove hook 25 | file: 26 | path: "/etc/network/if-up.d/{{ ffhb_routing_table }}" 27 | state: absent 28 | when: exit_ipv4 != "default" 29 | -------------------------------------------------------------------------------- /roles/exit-ipv4/tasks/generic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Open firewall for GRE 3 | copy: 4 | src: "10-allow-{{ exit_ipv4.lower() }}" 5 | dest: "{{ firewall_path }}/" 6 | mode: 0644 7 | owner: root 8 | group: root 9 | when: firewall_enabled 10 | notify: reload firewall 11 | 12 | - name: Install interfaces file 13 | template: 14 | src: generic/interface 15 | dest: "/etc/network/interfaces.d/{{ exit_ipv4_interface }}" 16 | mode: 0644 17 | owner: root 18 | group: root 19 | 20 | - name: Set interfaces up 21 | command: ifup {{ exit_ipv4_interface }} 22 | register: ifup_result 23 | changed_when: '"already configured" not in ifup_result.stderr' 24 | -------------------------------------------------------------------------------- /roles/exit-ipv4/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Include generic 3 | import_tasks: generic.yml 4 | when: exit_ipv4.lower() in ["gre", "ipip"] 5 | 6 | - name: Include default 7 | import_tasks: default.yml 8 | -------------------------------------------------------------------------------- /roles/exit-ipv4/templates/default/10-tcpmss-ipv4: -------------------------------------------------------------------------------- 1 | ipt4 -A FORWARD -i {{ main_bridge }} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1354 2 | ipt4 -A FORWARD -o {{ main_bridge }} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1354 3 | -------------------------------------------------------------------------------- /roles/exit-ipv4/templates/default/20-exit-ipv4: -------------------------------------------------------------------------------- 1 | {% if ipp2p_drop is defined and ipp2p_drop %} 2 | {% for protocol in ipp2p_protocols %} 3 | ipt4 -A FORWARD -i {{ main_bridge }} -o {{ exit_ipv4_interface }} -m ipp2p --{{protocol}} -j DROP 4 | ipt4 -A FORWARD -i {{ exit_ipv4_interface }} -o {{ main_bridge }} -m ipp2p --{{protocol}} -j DROP 5 | {% endfor %} 6 | {% endif %} 7 | 8 | # Traffic from our network to the Internet 9 | ipt4 -A FORWARD -i {{ main_bridge }} -o {{ exit_ipv4_interface }} -j ACCEPT 10 | ipt4 -A FORWARD -o {{ main_bridge }} -i {{ exit_ipv4_interface }} -j ACCEPT 11 | 12 | {% if exit_masquerade %} 13 | ipt4 -t nat -A POSTROUTING -s {{ ipv4_network }} -o {{ exit_ipv4_interface }} -j MASQUERADE 14 | {% endif %} 15 | -------------------------------------------------------------------------------- /roles/exit-ipv4/templates/default/up.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # Copy default route 4 | if [ "$IFACE" = "{{ ansible_default_ipv4.interface }}" ]; then 5 | if ! ip -4 route list 0/0 table '{{ ffhb_routing_table }}' | grep -q '^default'; then 6 | ip -4 route list 0/0 | xargs ip route add table '{{ ffhb_routing_table }}' 7 | fi 8 | fi 9 | -------------------------------------------------------------------------------- /roles/exit-ipv4/templates/generic/interface: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | auto {{ exit_ipv4_interface }} 4 | iface {{ exit_ipv4_interface }} inet manual 5 | mode {{ exit_ipv4 }} 6 | 7 | pre-up ip tunnel add $IFACE mode {{ exit_ipv4 }} remote {{ exit_ipv4_remote }} local {{ exit_ipv4_local }} ttl 255 8 | post-down ip tunnel del $IFACE 9 | 10 | up ip link set up dev $IFACE 11 | down ip link set down dev $IFACE 12 | 13 | up ip link set mtu {{ exit_ipv4_mtu }} dev $IFACE 14 | down ip link set mtu {{ exit_ipv4_mtu }} dev $IFACE 15 | 16 | # Set address to interface with scope link 17 | {% set exit_ipv4_prefix = exit_ipv4_address | ipaddr('host/prefix') | ipaddr('prefix') %} 18 | {% set exit_ipv4_address_plain = exit_ipv4_address | ipaddr('host/prefix') | ipaddr('address') %} 19 | {% if exit_ipv4_prefix == 32 %} 20 | up ip address add {{ exit_ipv4_address }} peer {{ exit_ipv4_address_peer }} scope link dev $IFACE 21 | down ip address del {{ exit_ipv4_address }} peer {{ exit_ipv4_address_peer }} scope link dev $IFACE 22 | {% else %} 23 | up ip address add {{ exit_ipv4_address }} dev $IFACE 24 | down ip address del {{ exit_ipv4_address }} dev $IFACE 25 | {% endif %} 26 | post-up ip rule add from {{ exit_ipv4_address_plain }} lookup default-freifunk priority 16385 27 | pre-down ip rule del from {{ exit_ipv4_address_plain }} lookup default-freifunk priority 16385 28 | 29 | {% if exit_ipv4_address_global %} 30 | # Set address for NAT 31 | post-up ip address add {{ exit_ipv4_address_global }}/32 dev $IFACE 32 | pre-down ip address del {{ exit_ipv4_address_global }}/32 dev $IFACE 33 | post-up ip rule add from {{ exit_ipv4_address_global }} lookup default-freifunk priority 16384 34 | pre-down ip rule del from {{ exit_ipv4_address_global }} lookup default-freifunk priority 16384 35 | {% endif %} 36 | 37 | # Default route 38 | post-up ip route add default via {{ exit_ipv4_address_peer }} dev $IFACE table {{ ffhb_routing_table }} 39 | pre-down ip route del default via {{ exit_ipv4_address_peer }} dev $IFACE table {{ ffhb_routing_table }} 40 | -------------------------------------------------------------------------------- /roles/exit-ipv6/README.md: -------------------------------------------------------------------------------- 1 | exit-ipv6 2 | ========================= 3 | 4 | Configure IPv6 exit 5 | 6 | 7 | Role Variables 8 | ------------------------ 9 | 10 | 11 | Usage 12 | ------------------------ 13 | 14 | - hosts: servers 15 | roles: 16 | - exit-ipv6 17 | 18 | 19 | License 20 | ------------------------ 21 | 22 | GPLv3 23 | -------------------------------------------------------------------------------- /roles/exit-ipv6/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | main_bridge: 'br-{{ site_code }}' 3 | -------------------------------------------------------------------------------- /roles/exit-ipv6/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/exit-ipv6/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install radv protocol for bird 3 | template: 4 | src: bird-radv.conf 5 | dest: /etc/bird/bird6.conf.d/radv.conf 6 | mode: 0644 7 | owner: root 8 | group: root 9 | notify: reload bird6 10 | 11 | - name: Configure firewall for IPv6 exit 12 | template: 13 | src: firewall.sh 14 | dest: "{{ firewall_path }}/20-exit-ipv6" 15 | mode: 0644 16 | owner: root 17 | group: root 18 | when: firewall_enabled 19 | notify: reload firewall 20 | -------------------------------------------------------------------------------- /roles/exit-ipv6/templates/bird-radv.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | protocol radv { 4 | interface "{{ main_bridge }}" { 5 | prefix {{ ipv6_local_address | ipaddr('network/prefix') }} {}; 6 | prefix {{ ipv6_global_address | ipaddr('network/prefix') }} {}; 7 | rdnss { 8 | ns {{ batman_ipv6_local.address }}; 9 | }; 10 | dnssl { 11 | domain "{{ site_domain }}"; 12 | lifetime mult 10; 13 | }; 14 | }; 15 | export where net = ::/0; 16 | }; 17 | -------------------------------------------------------------------------------- /roles/exit-ipv6/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt6 -A FORWARD -i '{{ main_bridge }}' -o '{{ exit_ipv6_interface }}' -j ACCEPT 2 | ipt6 -A FORWARD -o '{{ main_bridge }}' -i '{{ exit_ipv6_interface }}' -j ACCEPT 3 | ipt6 -A FORWARD -i '{{ main_bridge }}' -o '{{ main_bridge }}' -j ACCEPT 4 | ipt -A INPUT -p ipv6 -j ACCEPT 5 | -------------------------------------------------------------------------------- /roles/exit-ipv6/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ipv6_global_address: "{{ batman_ipv6_global.address }}/{{ batman_ipv6_global.size }}" 3 | ipv6_local_address: "{{ batman_ipv6_local.address }}/{{ batman_ipv6_local.size }}" 4 | -------------------------------------------------------------------------------- /roles/fail2ban/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Reload fail2ban 3 | ansible.builtin.systemd: 4 | name: fail2ban 5 | state: reloaded 6 | -------------------------------------------------------------------------------- /roles/fail2ban/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install fail2ban and dependencies 3 | ansible.builtin.apt: 4 | name: 5 | - fail2ban 6 | - python3-systemd 7 | - iptables 8 | - ipset 9 | 10 | - name: Configure fail2ban to use systemd-journald for its own logging 11 | community.general.ini_file: 12 | path: /etc/fail2ban/fail2ban.local 13 | section: Definition 14 | option: logtarget 15 | value: SYSLOG 16 | notify: Reload fail2ban 17 | 18 | - name: Configure fail2ban to parse systemd-journald for login failures 19 | community.general.ini_file: 20 | path: /etc/fail2ban/jail.local 21 | section: DEFAULT 22 | option: backend 23 | value: systemd 24 | notify: Reload fail2ban 25 | 26 | - name: Configure fail2ban to use ipsets 27 | community.general.ini_file: 28 | path: /etc/fail2ban/jail.local 29 | section: DEFAULT 30 | option: banaction 31 | value: iptables-ipset-proto6 32 | notify: Reload fail2ban 33 | 34 | - name: Configure fail2ban to be more strict 35 | community.general.ini_file: 36 | path: /etc/fail2ban/jail.local 37 | section: DEFAULT 38 | option: "{{ item.option }}" 39 | value: "{{ item.value }}" 40 | loop: 41 | - option: maxretry 42 | value: 3 43 | - option: bantime 44 | value: 30m 45 | notify: Reload fail2ban 46 | -------------------------------------------------------------------------------- /roles/fastd/README.md: -------------------------------------------------------------------------------- 1 | fastd 2 | ========================= 3 | 4 | Install fastd 5 | 6 | 7 | Configuration 8 | ------------------------- 9 | 10 | This role creates three instances of fastd: 11 | 12 | * `/etc/fastd/{{ site_code }}` listening on port 50000 (IPv4 and IPv6) 13 | * `/etc/fastd/{{ site_code }}-legacy` listening on port 10000 (IPv4 only) 14 | 15 | 16 | Usage 17 | ------------------------- 18 | 19 | - hosts: servers 20 | roles: 21 | - fastd 22 | 23 | 24 | License 25 | ------------------------- 26 | 27 | GPLv3 28 | -------------------------------------------------------------------------------- /roles/fastd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Interface-Namen dürfen maximal 15 Zeichen lang sein 3 | # http://lxr.free-electrons.com/source/include/uapi/linux/if.h?v=3.19#L26 4 | 5 | batman_interface: bat-{{ site_code }} 6 | 7 | fastd_peers_limit: -1 8 | fastd_anonymous: true 9 | 10 | fastd_interface: vpn-{{ site_code }} 11 | fastd_port: 50000 12 | fastd_mtu: 1280 13 | 14 | fastd_legacy_interface: vpn-{{ site_code }}-legacy 15 | fastd_legacy_port: 10000 16 | fastd_legacy_mtu: 1426 17 | 18 | fastd_blacklist_git_commit: '2b920b5e3009e075baffdfec8c27670388b43c96' 19 | -------------------------------------------------------------------------------- /roles/fastd/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart fastd 3 | service: 4 | name: "fastd@{{ item }}" 5 | state: restarted 6 | with_items: 7 | - "{{ site_code }}" 8 | - "{{ site_code }}_legacy" 9 | 10 | - name: reload systemd 11 | systemd: 12 | daemon_reload: yes 13 | -------------------------------------------------------------------------------- /roles/fastd/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - batman-adv-interface 4 | - firewall 5 | - git 6 | galaxy_info: 7 | platforms: 8 | - name: Debian 9 | versions: 10 | - wheezy 11 | - jessie 12 | -------------------------------------------------------------------------------- /roles/fastd/tasks/blacklist.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install JSON processor and dnsutils 3 | apt: 4 | name: 5 | - jq 6 | - dnsutils 7 | 8 | - name: Clone blacklist repository 9 | git: 10 | repo: "{{ site_git_root }}/vpn-blacklist/" 11 | dest: "/opt/{{ site_code }}/vpn-blacklist/" 12 | version: "{{ fastd_blacklist_git_commit }}" 13 | 14 | - name: Copy blacklist script 15 | command: cp /opt/{{ site_code }}/vpn-blacklist/blacklist.sh /etc/fastd/{{ site_code }}/blacklist.sh 16 | args: 17 | creates: /etc/fastd/{{ site_code }}/blacklist.sh 18 | 19 | - name: Install timer unit to automatically update blacklist repository 20 | template: 21 | src: '{{ item }}' 22 | dest: "/etc/systemd/system/" 23 | mode: 0644 24 | loop: 25 | - update-fastd-blacklist@.service 26 | - update-fastd-blacklist@.timer 27 | 28 | - name: Enable timer unit to automatically update blacklist repository 29 | systemd: 30 | name: "update-fastd-blacklist@{{ site_code }}.timer" 31 | enabled: yes 32 | state: started 33 | daemon_reload: yes 34 | 35 | - name: Remove obsolete cronjob 36 | file: 37 | path: "/etc/cron.hourly/update-fastd-blacklist-{{ site_code }}" 38 | state: absent 39 | -------------------------------------------------------------------------------- /roles/fastd/tasks/instance.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check interface length 3 | fail: 4 | msg: "{{ fastd_interface }} has more than 15 characters!" 5 | when: fastd_interface|length > 15 6 | 7 | - name: Create directories 8 | file: 9 | path: "/etc/fastd/{{ fastd_instance }}/peers" 10 | state: directory 11 | mode: 0755 12 | owner: root 13 | group: root 14 | 15 | - name: Upload fastd.conf 16 | template: 17 | src: fastd.conf 18 | dest: "/etc/fastd/{{ fastd_instance }}/" 19 | mode: 0644 20 | owner: root 21 | group: root 22 | notify: 23 | - restart fastd 24 | 25 | - name: Add network configuration 26 | template: 27 | src: interfaces 28 | dest: "/etc/network/interfaces.d/{{ fastd_interface }}" 29 | mode: 0644 30 | owner: root 31 | group: root 32 | 33 | - name: Open firewall for fastd 34 | template: 35 | src: firewall.sh 36 | dest: "{{ firewall_path }}/30-fastd-{{ fastd_instance }}" 37 | mode: 0644 38 | owner: root 39 | group: root 40 | when: firewall_enabled 41 | notify: reload firewall 42 | 43 | - name: Enable fastd instance 44 | service: 45 | name: "fastd@{{ fastd_instance }}" 46 | enabled: yes 47 | -------------------------------------------------------------------------------- /roles/fastd/templates/fastd.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | log to syslog level warn; 4 | hide ip addresses yes; 5 | status socket "/run/fastd-{{ fastd_instance }}.sock"; 6 | 7 | interface "{{ fastd_interface }}"; 8 | 9 | method "null"; 10 | method "salsa2012+umac"; 11 | method "salsa2012+gmac"; 12 | {% if ('backbone_legacy' in group_names) or ('downlinks_legacy' in group_names) or ('vpnservers_legacy' in group_names) %} 13 | method "xsalsa20-poly1305"; 14 | 15 | secure handshakes yes; 16 | {% endif %} 17 | 18 | bind {{ fastd_bind }}:{{ fastd_port }}; 19 | 20 | include "secret.conf"; 21 | 22 | mtu {{ fastd_mtu }}; 23 | 24 | {% if fastd_peers_limit > -1 %} 25 | peer limit {{ fastd_peers_limit }}; 26 | {% endif %} 27 | 28 | on up "ifup --allow hotplug {{ fastd_interface }}"; 29 | on down "ifdown --allow hotplug {{ fastd_interface }}"; 30 | 31 | {% if fastd_anonymous %} 32 | on verify "/etc/fastd/{{ site_code }}/blacklist.sh /opt/{{ site_code }}/vpn-blacklist/blacklist.json"; 33 | {% endif %} 34 | 35 | include peers from "peers"; 36 | -------------------------------------------------------------------------------- /roles/fastd/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt6 -A INPUT -p udp --dport '{{ fastd_port }}' -s 2002::/16 -j REJECT --reject-with icmp6-adm-prohibited 2 | ipt -A INPUT -p udp --dport '{{ fastd_port }}' -j ACCEPT 3 | -------------------------------------------------------------------------------- /roles/fastd/templates/interfaces: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | allow-hotplug {{ fastd_interface }} 4 | iface {{ fastd_interface }} inet manual 5 | up ip link set up $IFACE 6 | up batctl meshif {{ batman_interface }} if add $IFACE 7 | down batctl meshif {{ batman_interface }} if del $IFACE 8 | down ip link set down $IFACE 9 | -------------------------------------------------------------------------------- /roles/fastd/templates/peer.conf: -------------------------------------------------------------------------------- 1 | key "{{ item.value.key }}"; 2 | {% for remote in item.value.remotes %} 3 | remote {{ remote | regex_replace('(\d+)$', '') }} {{ fastd_port }}; 4 | {% endfor %} 5 | float yes; 6 | -------------------------------------------------------------------------------- /roles/fastd/templates/update-fastd-blacklist@.service: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | [Unit] 4 | Description=Update fastd blacklist for site %i 5 | 6 | [Service] 7 | ExecStart=/usr/bin/git -C /opt/%I/vpn-blacklist/ pull --rebase --quiet origin master 8 | Type=exec 9 | -------------------------------------------------------------------------------- /roles/fastd/templates/update-fastd-blacklist@.timer: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | [Unit] 4 | Description=Regularly update fastd blacklist for site %i 5 | 6 | [Timer] 7 | OnCalendar=hourly 8 | RandomizedDelaySec=1h 9 | FixedRandomDelay=yes 10 | 11 | [Install] 12 | WantedBy=timers.target 13 | -------------------------------------------------------------------------------- /roles/firewall/README.md: -------------------------------------------------------------------------------- 1 | firewall 2 | ========================= 3 | 4 | Configure firewall 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | vars: 12 | firewall_enabled: true 13 | roles: 14 | - firewall 15 | 16 | 17 | License 18 | ------------------------- 19 | 20 | GPLv3 21 | -------------------------------------------------------------------------------- /roles/firewall/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | firewall_enabled: false 3 | firewall_path: /etc/firewall.d 4 | -------------------------------------------------------------------------------- /roles/firewall/files/00-base: -------------------------------------------------------------------------------- 1 | # clear all tables, not only filter 2 | for table in $(iptables-save | grep '^*' | cut -d'*' -f2); do 3 | ipt -t $table -F 4 | ipt -t $table -X 5 | done 6 | 7 | ipt -P INPUT ACCEPT 8 | ipt -P OUTPUT ACCEPT 9 | ipt -P FORWARD ACCEPT 10 | 11 | ipt -A INPUT -i lo -j ACCEPT 12 | ipt4 -A INPUT -p icmp -j ACCEPT 13 | ipt6 -A INPUT -p ipv6-icmp -j ACCEPT 14 | -------------------------------------------------------------------------------- /roles/firewall/files/90-established: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/firewall/files/99-reject: -------------------------------------------------------------------------------- 1 | ipt4 -A INPUT -j REJECT --reject-with icmp-admin-prohibited 2 | ipt6 -A INPUT -j REJECT --reject-with icmp6-adm-prohibited 3 | ipt4 -A FORWARD -j REJECT --reject-with icmp-admin-prohibited 4 | ipt6 -A FORWARD -j REJECT --reject-with icmp6-adm-prohibited 5 | -------------------------------------------------------------------------------- /roles/firewall/files/firewall.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Firewall 3 | DefaultDependencies=no 4 | Before=network.target 5 | Requires=systemd-modules-load.service local-fs.target 6 | After=systemd-modules-load.service local-fs.target 7 | 8 | [Service] 9 | Type=oneshot 10 | RemainAfterExit=yes 11 | ExecStart=/etc/init.d/firewall.sh start 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /roles/firewall/files/ipv4-netfilter-ip-conntrack-max.conf: -------------------------------------------------------------------------------- 1 | net.netfilter.nf_conntrack_max = 131072 2 | -------------------------------------------------------------------------------- /roles/firewall/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload firewall 3 | service: 4 | name: firewall 5 | state: restarted 6 | 7 | - name: reload sysctl 8 | command: /sbin/sysctl --system 9 | -------------------------------------------------------------------------------- /roles/firewall/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/firewall/tasks/included.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages 3 | apt: 4 | name: iptables 5 | 6 | - name: Install xtables-addons-dkms 7 | apt: 8 | name: xtables-addons-dkms 9 | when: ipp2p_drop is defined and ipp2p_drop 10 | 11 | - name: Install firewall script 12 | template: 13 | src: init.sh 14 | dest: /etc/init.d/firewall.sh 15 | mode: 0755 16 | owner: root 17 | group: root 18 | 19 | - name: Install systemd unit 20 | copy: 21 | src: firewall.service 22 | dest: /etc/systemd/system/firewall.service 23 | mode: 0644 24 | owner: root 25 | group: root 26 | 27 | - name: Install basic firewall rules 28 | copy: 29 | src: "{{ item }}" 30 | dest: "{{ firewall_path }}/" 31 | mode: 0644 32 | owner: root 33 | group: root 34 | with_items: 35 | - 00-base 36 | - 90-established 37 | - 99-reject 38 | notify: reload firewall 39 | 40 | - name: Enable firewall service 41 | service: 42 | name: firewall 43 | enabled: yes 44 | 45 | - name: Add nf_conntrack to /etc/modules 46 | lineinfile: 47 | dest: /etc/modules 48 | line: nf_conntrack 49 | regexp: '^nf_conntrack' 50 | 51 | - name: Copy sysctl file for conntrack 52 | copy: 53 | src: ipv4-netfilter-ip-conntrack-max.conf 54 | dest: /etc/sysctl.d/ 55 | mode: 0644 56 | owner: root 57 | group: root 58 | notify: reload sysctl 59 | 60 | - name: Create rc.local 61 | copy: 62 | content: "#!/bin/sh -e\nexit 0\n" 63 | dest: /etc/rc.local 64 | mode: 0755 65 | owner: root 66 | group: root 67 | force: no 68 | 69 | - name: Add sysctl call to /etc/rc.local 70 | lineinfile: 71 | name: /etc/rc.local 72 | insertbefore: "^exit" 73 | line: "sysctl --quiet --load=/etc/sysctl.d/ipv4-netfilter-ip-conntrack-max.conf" 74 | regexp: '^sysctl --quiet --load=/etc/sysctl.d/ipv4-netfilter-ip-conntrack-max\.conf$' 75 | create: yes 76 | mode: 0755 77 | 78 | - name: Uninstall iptables-persistent 79 | apt: 80 | name: netfilter-persistent 81 | state: absent 82 | -------------------------------------------------------------------------------- /roles/firewall/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - import_tasks: included.yml 3 | when: firewall_enabled 4 | -------------------------------------------------------------------------------- /roles/firewall/templates/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: firewall.sh 5 | # Required-Start: mountkernfs $remote_fs 6 | # Required-Stop: $remote_fs 7 | # Default-Start: S 8 | # Default-Stop: 0 1 6 9 | # Short-Description: Load boot-time netfilter configuration 10 | # Description: Loads boot-time netfilter configuration 11 | ### END INIT INFO 12 | 13 | set -eu 14 | 15 | RULEPATH="${RULEPATH:-"{{ firewall_path }}"}" 16 | 17 | new_rule() { 18 | for arg in "$@"; do 19 | case "$arg" in 20 | -I|-A) 21 | comment="Set by file $rule" 22 | ;; 23 | --comment) 24 | comment="" 25 | break 26 | ;; 27 | esac 28 | done 29 | 30 | "$@" ${comment:+-m comment --comment "${comment}"} \ 31 | || echo "$@" ${comment:+-m comment --comment "${comment}"} 32 | } 33 | 34 | ipt() { 35 | ipt4 "$@" 36 | ipt6 "$@" 37 | } 38 | 39 | ipt4() { 40 | new_rule iptables "$@" 41 | } 42 | 43 | ipt6() { 44 | new_rule ip6tables "$@" 45 | } 46 | 47 | case "$1" in 48 | start|restart) 49 | for rule in "$RULEPATH"/*; do 50 | # shellcheck disable=SC1090 51 | . "$rule" 52 | done 53 | ;; 54 | *) 55 | echo "Action $1 unsupported" 56 | esac 57 | -------------------------------------------------------------------------------- /roles/freifunkmanager/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | freifunkmanager_caddy: true 3 | freifunkmanager_webserver_bind: "127.0.0.1:8080" 4 | freifunkmanager_webroot: "/opt/go/src/github.com/FreifunkBremen/freifunkmanager/webroot" 5 | 6 | freifunkmanager_state_path: "freifunkmanager.json" 7 | freifunkmanager_ssh_interface: "eth0" 8 | freifunkmanager_ssh_key: .ssh/id_rsa 9 | 10 | freifunkmanager_yanic: true 11 | freifunkmanager_yanic_type: unix 12 | freifunkmanager_yanic_address: "/var/lib/yanic-database.socket" 13 | -------------------------------------------------------------------------------- /roles/freifunkmanager/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart freifunkmanager 3 | service: 4 | name: freifunkmanager 5 | state: restarted 6 | 7 | - name: reload caddy 8 | service: 9 | name: caddy 10 | state: reloaded 11 | 12 | - name: reload systemd 13 | systemd: 14 | daemon_reload: yes 15 | -------------------------------------------------------------------------------- /roles/freifunkmanager/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - go 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - jessie 9 | -------------------------------------------------------------------------------- /roles/freifunkmanager/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create users 3 | user: 4 | name: freifunkmanager 5 | generate_ssh_key: yes 6 | ssh_key_type: rsa 7 | ssh_key_file: .ssh/id_rsa 8 | ssh_key_comment: "yanic@{{ inventory_hostname }}" 9 | 10 | - name: Install yanic 11 | command: 12 | cmd: /usr/local/go/bin/go get -u github.com/FreifunkBremen/freifunkmanager/cmd/freifunkmanager 13 | creates: /opt/go/bin/freifunkmanager 14 | environment: 15 | GOPATH: /opt/go 16 | notify: 17 | - restart freifunkmanager 18 | 19 | - name: Configure freifunkmanager 20 | template: 21 | src: config.toml 22 | dest: /etc/freifunkmanager.conf 23 | mode: 0644 24 | owner: root 25 | group: root 26 | notify: 27 | - restart freifunkmanager 28 | 29 | - name: Configure caddy 30 | template: 31 | src: caddy 32 | dest: /etc/caddy/hosts/10-freifunkmanager.act 33 | mode: 0644 34 | owner: root 35 | group: root 36 | when: freifunkmanager_caddy 37 | notify: 38 | - reload caddy 39 | 40 | - name: Create directory 41 | file: 42 | path: "{{ yanic_meshviewer_path }}/" 43 | state: directory 44 | mode: 0755 45 | owner: yanic 46 | group: yanic 47 | 48 | - name: Install system unit 49 | template: 50 | src: freifunkmanager.service 51 | dest: /lib/systemd/system/freifunkmanager.service 52 | mode: 0644 53 | owner: root 54 | group: root 55 | notify: 56 | - reload systemd 57 | - restart yanic 58 | 59 | - name: Enable freifunkmanager 60 | service: 61 | name: freifunkmanager 62 | enabled: yes 63 | -------------------------------------------------------------------------------- /roles/freifunkmanager/templates/caddy: -------------------------------------------------------------------------------- 1 | http://{{freifunkmanager_domain}} { 2 | redir https://{{freifunkmanager_domain}}{uri} 3 | } 4 | https://{{freifunkmanager_domain}} { 5 | tls {{freifunkmanager_email}} 6 | gzip 7 | basicauth / ffhb {{freifunkmanager_password}} 8 | index index.html 9 | 10 | push / /img/logo.png 11 | push / /css/images/layers.png 12 | push / /css/leaflet.css 13 | push / /css/main.css 14 | push / /css/map.css 15 | push / /js/moment.js 16 | push / /js/navigo.js 17 | push / /js/leaflet.js 18 | push / /js/leaflet.ajax.min.js 19 | push / /js/webgl-heatmap.js 20 | push / /js/leaflet-webgl-heatmap.min.js 21 | push / /js/config.js 22 | push / /js/domlib.js 23 | push / /js/store.js 24 | push / /js/notify.js 25 | push / /js/gui_list.js 26 | push / /js/gui_map.js 27 | push / /js/gui_node.js 28 | push / /js/gui_stats.js 29 | push / /js/gui.js 30 | push / /js/socket.js 31 | push / /js/app.js 32 | 33 | 34 | root /opt/go/src/github.com/FreifunkBremen/freifunkmanager/webroot 35 | proxy /websocket {{freifunkmanager_webserver_bind}} { 36 | header_upstream Host {host} 37 | header_upstream X-Real-IP {remote} 38 | header_upstream X-Forwarded-For {remote} 39 | header_upstream X-Forwarded-Proto {scheme} 40 | websocket 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /roles/freifunkmanager/templates/config.toml: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | webserver_bind = "{{freifunkmanager_webserver_bind}}" 3 | webroot = "{{freifunkmanager_webroot}}" 4 | 5 | state_path = "{{freifunkmanager_state_path}}" 6 | 7 | ssh_key = "{{freifunkmanager_ssh_key}}" 8 | ssh_interface = "{{freifunkmanager_ssh_interface}}" 9 | 10 | [yanic] 11 | enable = {{freifunkmanager_yanic | ternary('true','false') }} 12 | type = "{{freifunkmanager_yanic_type}}" 13 | address = "{{freifunkmanager_yanic_address}}" 14 | -------------------------------------------------------------------------------- /roles/freifunkmanager/templates/freifunkmanager.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=freifunkmanager 3 | 4 | [Service] 5 | Type=simple 6 | ExecStart=/opt/go/bin/freifunkmanager -config /etc/freifunkmanager.conf 7 | Restart=always 8 | RestartSec=5s 9 | Environment=PATH=/usr/bin:/usr/local/bin 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /roles/gatemon/README.md: -------------------------------------------------------------------------------- 1 | gatemon 2 | ========================= 3 | 4 | Installing gatemon 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - gatemon 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/gatemon/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gatemon_email: 'gatemon@bremen.freifunk.net' 3 | gatemon_user: 'gatemon' 4 | gatemon_group: 'gatemon' 5 | gatemon_subdomain: 'status' 6 | gatemon_domain: '{{ gatemon_subdomain }}.{{ main_domain }}' 7 | gatemon_git_root: 'https://github.com/FreifunkBremen/gatemon-html.git' 8 | gatemon_git_version: 'v0.8' 9 | -------------------------------------------------------------------------------- /roles/gatemon/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | command: 4 | cmd: /usr/bin/composer install 5 | chdir: /var/www/{{ gatemon_user }}/domains/{{ gatemon_domain }} 6 | become: yes 7 | become_user: "{{ gatemon_user }}" 8 | -------------------------------------------------------------------------------- /roles/gatemon/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - sudo 4 | - apache 5 | - letsencrypt 6 | - php 7 | - git 8 | galaxy_info: 9 | platforms: 10 | - name: Debian 11 | versions: 12 | - jessie 13 | -------------------------------------------------------------------------------- /roles/gatemon/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ gatemon_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ gatemon_subdomain }}.{{ alt_domain }} 6 | 7 | # Enable HTTPS proxying 8 | SSLProxyEngine On 9 | 10 | # Don't add header to proxy 11 | ProxyAddHeaders Off 12 | 13 | # set this to customers mail address 14 | ServerAdmin {{ gatemon_email }} 15 | 16 | SuexecUserGroup {{ gatemon_user }} {{ gatemon_group }} 17 | 18 | DocumentRoot /var/www/{{ gatemon_user }}/domains/{{ gatemon_domain }} 19 | 20 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 21 | Options +SymLinksIfOwnerMatch -Includes 22 | 23 | 24 | Alias /icons /usr/share/apache2/icons 25 | ScriptAlias /cgi-bin /var/www/{{ gatemon_user }}/cgi-bin 26 | ScriptAlias /fcgi-bin /var/www/{{ gatemon_user }}/fcgi-bin 27 | Include /etc/apache2/user-php-exec.conf 28 | 29 | ErrorLog /var/log/apache2/{{ gatemon_user }}/{{ gatemon_domain }}-error.log 30 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 31 | 32 | SSLEngine on 33 | SSLCertificateFile /etc/letsencrypt/certs/{{ gatemon_domain }}/fullchain.pem 34 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ gatemon_domain }}/privkey.pem 35 | 36 | -------------------------------------------------------------------------------- /roles/gatemon/templates/php-fcgi-starter: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # Set safe path 4 | export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 5 | 6 | # Set user environment 7 | export USER={{ gatemon_user }} 8 | export HOME=/home/{{ gatemon_user }} 9 | 10 | PHP_FCGI_CHILDREN=0 11 | export PHP_FCGI_CHILDREN 12 | PHP_FCGI_MAX_REQUESTS=250 13 | export PHP_FCGI_MAX_REQUESTS 14 | exec php-cgi 15 | -------------------------------------------------------------------------------- /roles/git/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install git 3 | apt: 4 | name: git 5 | 6 | - name: Install ca-certificates 7 | apt: 8 | name: ca-certificates 9 | -------------------------------------------------------------------------------- /roles/go/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Download and install go 3 | unarchive: 4 | src: https://golang.org/dl/go1.17.1.linux-amd64.tar.gz 5 | dest: /usr/local 6 | copy: no 7 | 8 | - name: Configure go 9 | template: 10 | src: go.sh 11 | dest: /etc/profile.d/go.sh 12 | mode: 0644 13 | owner: root 14 | group: root 15 | -------------------------------------------------------------------------------- /roles/go/templates/go.sh: -------------------------------------------------------------------------------- 1 | export GOPATH=/opt/go 2 | export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin 3 | -------------------------------------------------------------------------------- /roles/grafana/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | In influxdb: 5 | 6 | CREATE USER "grafana" WITH PASSWORD 'grafana' 7 | -------------------------------------------------------------------------------- /roles/grafana/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | grafana_email: 'info@bremen.freifunk.net' 3 | grafana_subdomain: grafana 4 | grafana_domain: '{{ grafana_subdomain }}.{{ main_domain }}' 5 | grafana_addr: 127.0.0.1 6 | grafana_port: 8080 7 | grafana_caddy: false 8 | 9 | # caddy support only 10 | grafana_location: "" 11 | -------------------------------------------------------------------------------- /roles/grafana/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart grafana 3 | service: 4 | name: grafana-server 5 | state: restarted 6 | 7 | - name: regenerate certificates 8 | command: /opt/dehydrated/dehydrated -f /etc/letsencrypt/config -c 9 | 10 | - name: reload apache 11 | service: 12 | name: apache2 13 | state: reloaded 14 | 15 | - name: reload caddy 16 | service: 17 | name: caddy 18 | state: reloaded 19 | -------------------------------------------------------------------------------- /roles/grafana/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ grafana_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ grafana_subdomain }}.{{ alt_domain }} 6 | 7 | # set this to customers mail address 8 | ServerAdmin {{ grafana_email }} 9 | 10 | ProxyPass / http://{{ grafana_addr }}:{{ grafana_port }}/ 11 | 12 | # Sets CORS headers for request from example1.com and example2.com pages 13 | # for both SSL and non-SSL 14 | SetEnvIf Origin "^https?://[^/]*(ffhb\.de|bremen\.freifunk\.net)$" ORIGIN=$0 15 | Header set Access-Control-Allow-Origin %{ORIGIN}e env=ORIGIN 16 | Header set Access-Control-Allow-Credentials "true" env=ORIGIN 17 | # Always set Vary: Origin when it's possible you may send CORS headers 18 | Header merge Vary Origin 19 | 20 | # Don't add header to proxy 21 | ProxyAddHeaders Off 22 | 23 | # cache tiles for 7 days on disk, ignoring client refreshes 24 | CacheEnable disk / 25 | CacheDisable /.well-known/acme-challenge 26 | CacheDisable /api 27 | CacheDisable /render 28 | CacheDefaultExpire 604800 29 | CacheIgnoreCacheControl on 30 | CacheIgnoreQueryString on 31 | # this unifies the cache for HTTP and HTTPS 32 | CacheKeyBaseURL "http://{{ grafana_domain }}/" 33 | 34 | SSLEngine on 35 | SSLCertificateFile /etc/letsencrypt/certs/{{ grafana_domain }}/fullchain.pem 36 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ grafana_domain }}/privkey.pem 37 | 38 | -------------------------------------------------------------------------------- /roles/grafana/templates/caddy: -------------------------------------------------------------------------------- 1 | https://{{grafana_domain}}{{grafana_location}} { 2 | tls {{grafana_email}} 3 | gzip 4 | proxy / {{ grafana_addr }}:{{ grafana_port }} 5 | } 6 | -------------------------------------------------------------------------------- /roles/grafana/templates/grafana.ini: -------------------------------------------------------------------------------- 1 | [server] 2 | http_addr = {{ grafana_addr }} 3 | http_port = {{ grafana_port }} 4 | root_url = https://{{grafana_domain}}{{grafana_location}} 5 | 6 | [analytics] 7 | check_for_updates = true 8 | 9 | [auth.anonymous] 10 | enabled = true 11 | 12 | [log] 13 | # Either "console", "file", "syslog". Default is console and file 14 | # Use comma to separate multiple modes, e.g. "console, file" 15 | mode = console 16 | level = Warn 17 | 18 | [dashboards.json] 19 | enabled = true 20 | path = /var/lib/grafana/dashboards 21 | -------------------------------------------------------------------------------- /roles/group-webusers/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Added webusers group 3 | group: 4 | name: webusers 5 | state: present 6 | -------------------------------------------------------------------------------- /roles/influxdb/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p tcp --dport 8083 -j ACCEPT 2 | ipt -A INPUT -p tcp --dport 8086 -j ACCEPT 3 | -------------------------------------------------------------------------------- /roles/influxdb/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/letsencrypt/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | letsencrypt_git_root: 'https://github.com/lukas2511/dehydrated.git' 3 | letsencrypt_git_commit: '05eda91a2fbaed1e13c733230238fc68475c535e' 4 | -------------------------------------------------------------------------------- /roles/letsencrypt/files/acme-challenge.conf: -------------------------------------------------------------------------------- 1 | Alias /.well-known/acme-challenge /var/www/acme-challenge 2 | 3 | Require all granted 4 | 5 | 6 | ProxyPass /.well-known/acme-challenge ! 7 | 8 | 9 | CacheDisable /.well-known/acme-challenge 10 | 11 | 12 | RewriteOptions InheritDownBefore 13 | RewriteRule ^/.well-known/acme-challenge - [L] 14 | 15 | -------------------------------------------------------------------------------- /roles/letsencrypt/files/cronjob: -------------------------------------------------------------------------------- 1 | 0 */12 * * * root test -x /opt/dehydrated/dehydrated && perl -e 'sleep int(rand(3600))' && chronic /opt/dehydrated/dehydrated -f /etc/letsencrypt/config -c -g 2 | -------------------------------------------------------------------------------- /roles/letsencrypt/files/hook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "$1" in 4 | deploy_cert) 5 | systemctl reload apache2 6 | esac 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /roles/letsencrypt/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: regenerate certificates 3 | command: /opt/dehydrated/dehydrated -f /etc/letsencrypt/config -c 4 | -------------------------------------------------------------------------------- /roles/letsencrypt/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create directory for letsencrypt challenges 3 | file: 4 | path: /var/www/acme-challenge 5 | state: directory 6 | mode: 0750 7 | owner: root 8 | group: www-data 9 | 10 | - name: Install Apache config for letsencrypt challenges 11 | copy: 12 | src: acme-challenge.conf 13 | dest: /etc/apache2/conf-available/acme-challenge.conf 14 | mode: 0644 15 | owner: root 16 | group: root 17 | 18 | - name: Enable Apache config for letsencrypt challenges 19 | command: a2enconf acme-challenge.conf 20 | args: 21 | creates: /etc/apache2/conf-enabled/acme-challenge.conf 22 | 23 | - name: Install letsencrypt client 24 | git: 25 | repo: "{{ letsencrypt_git_root }}" 26 | version: "{{ letsencrypt_git_commit }}" 27 | dest: '/opt/dehydrated/' 28 | 29 | - name: Create config directory for letsencrypt client 30 | file: 31 | path: /etc/letsencrypt 32 | state: directory 33 | mode: 0755 34 | owner: root 35 | group: root 36 | 37 | - name: Copy letsencrypt client config 38 | copy: 39 | src: config 40 | dest: /etc/letsencrypt/config 41 | mode: 0644 42 | owner: root 43 | group: root 44 | notify: regenerate certificates 45 | 46 | - name: Copy letsencrypt client hook script 47 | copy: 48 | src: hook.sh 49 | dest: /etc/letsencrypt/hook.sh 50 | mode: 0755 51 | owner: root 52 | group: root 53 | notify: regenerate certificates 54 | 55 | - name: Copy letsencrypt cronjob 56 | copy: 57 | src: cronjob 58 | dest: /etc/cron.d/letsencrypt 59 | mode: 0644 60 | owner: root 61 | group: root 62 | -------------------------------------------------------------------------------- /roles/main-bridge/README.md: -------------------------------------------------------------------------------- 1 | main-bridge 2 | ========================= 3 | 4 | Install the bridge for Freifunk Bremen VPN gateways 5 | 6 | 7 | Role Variables 8 | ------------------------- 9 | 10 | ffhb_routing_table: Routing table for default gateway via VPN and ICVPN (default: default-freifunk) 11 | batman_interface: Interface on which works Batman (default: 'bat-{{ site_code }}' ) 12 | 13 | 14 | Usage 15 | ------------------------- 16 | 17 | - hosts: servers 18 | vars: 19 | site_code: ffhb 20 | roles: 21 | - main-bridge 22 | 23 | 24 | License 25 | ------------------------- 26 | 27 | GPLv3 28 | -------------------------------------------------------------------------------- /roles/main-bridge/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | batman_interface: bat-{{ site_code }} 3 | ffhb_routing_table: default-freifunk 4 | -------------------------------------------------------------------------------- /roles/main-bridge/files/bridge-filter.conf: -------------------------------------------------------------------------------- 1 | net.bridge.bridge-nf-call-ip6tables = 0 2 | net.bridge.bridge-nf-call-iptables = 0 3 | net.bridge.bridge-nf-call-arptables = 0 4 | -------------------------------------------------------------------------------- /roles/main-bridge/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload sysctl 3 | command: /sbin/sysctl --system 4 | -------------------------------------------------------------------------------- /roles/main-bridge/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install bridge-utils 3 | apt: 4 | name: bridge-utils 5 | 6 | - name: Create batman routing table 7 | lineinfile: 8 | dest: /etc/iproute2/rt_tables 9 | line: "252 {{ ffhb_routing_table }}" 10 | regexp: "^252 " 11 | 12 | - name: Install interfaces file 13 | template: 14 | src: interfaces 15 | dest: "/etc/network/interfaces.d/br-{{ site_code }}" 16 | mode: 0644 17 | owner: root 18 | group: root 19 | 20 | - name: Copy sysctl file to disable bridge firewall filtering 21 | copy: 22 | src: bridge-filter.conf 23 | dest: /etc/sysctl.d/bridge-filter.conf 24 | mode: 0644 25 | owner: root 26 | group: root 27 | notify: reload sysctl 28 | 29 | - name: Copy sysctl file tuning neighbor discovery 30 | template: 31 | src: main-bridge-ip-neigh-tuning.conf 32 | dest: /etc/sysctl.d/main-bridge-ip-neigh-tuning.conf 33 | mode: 0644 34 | owner: root 35 | group: root 36 | notify: reload sysctl 37 | 38 | - name: Set interfaces up 39 | command: ifup br-{{ site_code }} 40 | register: ifup_result 41 | changed_when: '"already configured" not in ifup_result.stderr' 42 | -------------------------------------------------------------------------------- /roles/main-bridge/templates/main-bridge-ip-neigh-tuning.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.neigh.br-{{ site_code }}.gc_stale_time = 120 2 | net.ipv4.neigh.br-{{ site_code }}.base_reachable_time_ms = 1800000 3 | net.ipv4.neigh.br-{{ site_code }}.mcast_solicit = 1 4 | net.ipv6.neigh.br-{{ site_code }}.gc_stale_time = 120 5 | net.ipv6.neigh.br-{{ site_code }}.base_reachable_time_ms = 120000 6 | net.ipv6.neigh.br-{{ site_code }}.mcast_solicit = 1 7 | 8 | {% if 'downlinks' in group_names or 'downlinks_legacy' in group_names %} 9 | net.ipv6.neigh.default.gc_thresh1 = 4096 10 | net.ipv6.neigh.default.gc_thresh2 = 8192 11 | net.ipv6.neigh.default.gc_thresh3 = 16384 12 | {% else %} 13 | # gc_thresh1 = size of DHCP pool (minimum number of cached neighbor entries) 14 | net.ipv4.neigh.default.gc_thresh1 = 2560 15 | net.ipv4.neigh.default.gc_thresh2 = 3072 16 | net.ipv4.neigh.default.gc_thresh3 = 4096 17 | 18 | net.ipv6.neigh.default.gc_thresh1 = 1024 19 | net.ipv6.neigh.default.gc_thresh2 = 2048 20 | net.ipv6.neigh.default.gc_thresh3 = 3072 21 | {% endif %} 22 | -------------------------------------------------------------------------------- /roles/mesh-announce/README.md: -------------------------------------------------------------------------------- 1 | respondd 2 | ========================= 3 | 4 | Install respondd from git repo with systemd unit and alfred to announce informations 5 | 6 | 7 | Role Variables 8 | ------------------------- 9 | 10 | mesh_announce_git_root: (default: 'https://github.com/ffnord/mesh-announce/') 11 | 12 | 13 | Usage 14 | ------------------------- 15 | 16 | - hosts: servers 17 | vars: 18 | site_code: ffhb 19 | roles: 20 | - mesh-announce 21 | 22 | License 23 | ------------------------- 24 | 25 | GPLv3 26 | -------------------------------------------------------------------------------- /roles/mesh-announce/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | mesh_announce_git_root: 'https://github.com/ffnord/mesh-announce/' 3 | mesh_announce_git_commit: 'c34d9f203aba41d1b68967a69e517eb4c0962851' 4 | batman_interface: 'bat-{{ site_code }}' 5 | main_bridge: 'br-{{ site_code }}' 6 | 7 | # alfred 8 | mesh_announce_alfred: false 9 | alfred_master: False 10 | alfred_mtu_interface: 'br-{{ site_code }}-mtu' 11 | 12 | # respondds 13 | respondd_vpn: true 14 | -------------------------------------------------------------------------------- /roles/mesh-announce/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart respondd 3 | service: 4 | name: respondd 5 | state: restarted 6 | 7 | - name: reload systemd 8 | systemd: 9 | daemon_reload: yes 10 | -------------------------------------------------------------------------------- /roles/mesh-announce/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - git 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - wheezy 9 | - jessie 10 | -------------------------------------------------------------------------------- /roles/mesh-announce/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install needed tools 3 | apt: 4 | name: ethtool 5 | 6 | - name: Clone respondd announce repository 7 | git: 8 | repo: "{{ mesh_announce_git_root }}" 9 | dest: "/opt/{{ site_code }}/mesh-announce/" 10 | version: "{{ mesh_announce_git_commit }}" 11 | notify: 12 | - restart respondd 13 | 14 | - name: Install system unit 15 | template: 16 | src: service 17 | dest: /etc/systemd/system/respondd.service 18 | mode: 0644 19 | owner: root 20 | group: root 21 | notify: 22 | - reload systemd 23 | - restart respondd 24 | 25 | - name: Enable respondd 26 | service: 27 | name: respondd 28 | enabled: yes 29 | 30 | - name: Install cronjob to automatically update alfred announce 31 | template: 32 | src: cronjob 33 | dest: /etc/cron.d/mesh-announce-alfred 34 | mode: 0644 35 | owner: root 36 | group: root 37 | when: mesh_announce_alfred 38 | 39 | - name: Open firewall for respondd 40 | template: 41 | src: firewall.sh 42 | dest: "{{ firewall_path }}/30-respondd" 43 | mode: 0644 44 | owner: root 45 | group: root 46 | when: firewall_enabled 47 | notify: reload firewall 48 | -------------------------------------------------------------------------------- /roles/mesh-announce/templates/cronjob: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 3 | {% if alfred_master %} 4 | * * * * * root sh /opt/{{ site_code }}/mesh-announce/announce.sh -i {{ alfred_mtu_interface }} -b {{ batman_interface }} 5 | {% else %} 6 | * * * * * root sh /opt/{{ site_code }}/mesh-announce/announce.sh -i {{ main_bridge }} -b {{ batman_interface }} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /roles/mesh-announce/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt6 -A INPUT -i '{{ main_bridge }}' -p udp --dport 1001 -j ACCEPT 2 | ipt6 -A INPUT -i 'vpn-{{ site_code }}-legacy' -p udp --dport 1001 -j ACCEPT 3 | ipt6 -A INPUT -i 'vpn-{{ site_code }}' -p udp --dport 1001 -j ACCEPT 4 | -------------------------------------------------------------------------------- /roles/mesh-announce/templates/service: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [Unit] 3 | Description=Respondd 4 | After=network.target 5 | 6 | [Service] 7 | {% if respondd_vpn %} 8 | ExecStart=/opt/{{ site_code }}/mesh-announce/respondd.py -d /opt/{{ site_code }}/mesh-announce/providers -b {{ batman_interface }} -i {{ main_bridge }} -i vpn-{{ site_code }}-legacy -i vpn-{{ site_code }} 9 | {% else %} 10 | ExecStart=/opt/{{ site_code }}/mesh-announce/respondd.py -d /opt/{{ site_code }}/mesh-announce/providers -b {{ ansible_default_ipv4.interface }} -i {{ ansible_default_ipv4.interface }} 11 | {% endif %} 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /roles/meshviewer/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | meshviewer_git_root: "{{ site_git_root }}/meshviewer.git" 3 | meshviewer_git_version: '19bc3e505e6ac265210f20741b1e372ef598ce1e' 4 | meshviewer_path_bin: '/var/www/html/meshviewer' 5 | meshviewer_path_src: '/usr/src/meshviewer' 6 | 7 | meshviewer_apache: true 8 | 9 | meshviewer_geojson: false 10 | meshviewer_geojson_git_root: 'https://github.com/FreifunkBremen/internal-maps.git' 11 | meshviewer_geojson_git_commit: '69dcaa8a22885549b89038c51d49d2470eec56bf' 12 | meshviewer_geojson_file: 'meshviewer.geojson' 13 | meshviewer_geojson_file_path: '/var/www/html/data' 14 | -------------------------------------------------------------------------------- /roles/meshviewer/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - apt 4 | - git 5 | - nodejs 6 | galaxy_info: 7 | platforms: 8 | - name: Debian 9 | versions: 10 | - jessie 11 | -------------------------------------------------------------------------------- /roles/meshviewer/tasks/apache.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get letsencrypt certificates 3 | lineinfile: 4 | dest: /etc/letsencrypt/domains.txt 5 | line: "{{ meshviewer_subdomain }}.{{ main_domain }} {{ meshviewer_subdomain }}.{{ alt_domain }}" 6 | create: yes 7 | mode: 0644 8 | owner: root 9 | group: root 10 | when: meshviewer_subdomain is defined 11 | notify: regenerate certificates 12 | 13 | - name: Install Apache vHost config 14 | template: 15 | src: apache2.conf 16 | dest: "/etc/apache2/sites-available/{{ filename }}.conf" 17 | mode: 0644 18 | owner: root 19 | group: root 20 | notify: reload apache 21 | vars: 22 | filename: "{{ meshviewer_subdomain is defined | ternary(meshviewer_subdomain + '.' + main_domain, meshviewer_domain) }}" 23 | 24 | - name: Enable Apache vHost config 25 | command: a2ensite {{ filename }} 26 | args: 27 | creates: /etc/apache2/sites-enabled/{{ filename }}.conf 28 | notify: reload apache 29 | vars: 30 | filename: "{{ meshviewer_subdomain is defined | ternary(meshviewer_subdomain + '.' + main_domain, meshviewer_domain) }}" 31 | -------------------------------------------------------------------------------- /roles/meshviewer/tasks/geojson.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Clone repository 3 | git: 4 | repo: "{{ meshviewer_geojson_git_root }}" 5 | dest: "/opt/meshviewer_geojson_git" 6 | force: yes 7 | version: "{{ meshviewer_geojson_git_commit }}" 8 | 9 | - name: Install script to copy valide geojson 10 | template: 11 | src: geojson-update.sh 12 | dest: /usr/local/bin/geojson-update 13 | owner: root 14 | group: root 15 | mode: 0755 16 | 17 | - name: Install cronjob to copy valide geojson 18 | template: 19 | src: geojson.cronjob 20 | dest: /etc/cron.d/geojson-update 21 | owner: root 22 | group: root 23 | mode: 0644 24 | -------------------------------------------------------------------------------- /roles/meshviewer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install yarn 3 | npm: 4 | name: yarn 5 | global: yes 6 | 7 | - name: Clone repository 8 | git: 9 | repo: "{{ meshviewer_git_root }}" 10 | dest: "{{ meshviewer_path_src }}/" 11 | version: "{{ meshviewer_git_version }}" 12 | force: yes 13 | 14 | - name: Install node dependencies 15 | command: node /usr/bin/yarn install 16 | args: 17 | chdir: "{{ meshviewer_path_src }}" 18 | creates: node_modules 19 | 20 | - name: Build meshviewer 21 | command: node_modules/.bin/gulp 22 | args: 23 | chdir: "{{ meshviewer_path_src }}" 24 | creates: build 25 | 26 | - name: Create destination directory 27 | file: 28 | path: "{{ meshviewer_path_bin }}" 29 | state: directory 30 | mode: 0755 31 | owner: root 32 | group: root 33 | 34 | - name: Install rsync 35 | apt: 36 | name: rsync 37 | 38 | # does not work (https://github.com/ansible/ansible/issues/11873) 39 | #- name: Copy generated files 40 | # delegate_to: "{{ inventory_hostname }}" 41 | # synchronize: 42 | # src: {{ meshviewer_path_src }}/build/ 43 | # dest: {{ meshviewer_path_bin }}/ 44 | # delete: True 45 | # rsync_opts: 46 | # - "--exclude=config.json" 47 | 48 | - name: Copy files 49 | command: > 50 | rsync -a --delete 51 | {{ meshviewer_path_src }}/build/ 52 | {{ meshviewer_path_bin }}/ 53 | 54 | - name: Enable Apache 55 | include: apache.yml 56 | when: meshviewer_apache 57 | 58 | - name: Enable Geojson 59 | import_tasks: geojson.yml 60 | when: meshviewer_geojson 61 | -------------------------------------------------------------------------------- /roles/meshviewer/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | {% if meshviewer_subdomain is defined %} 5 | ServerName {{ meshviewer_subdomain }}.{{ main_domain }} 6 | ServerAlias {{ meshviewer_subdomain }}.{{ alt_domain }} 7 | {% else %} 8 | ServerName {{ meshviewer_domain }} 9 | {% endif %} 10 | 11 | ServerAdmin {{ meshviewer_email }} 12 | 13 | DocumentRoot {{ meshviewer_path_bin }} 14 | Alias /icons /usr/share/apache2/icons 15 | 16 | SSLEngine on 17 | SSLCertificateFile /etc/letsencrypt/certs/{{ meshviewer_domain }}/fullchain.pem 18 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ meshviewer_domain }}/privkey.pem 19 | 20 | -------------------------------------------------------------------------------- /roles/meshviewer/templates/geojson-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MAP_GIT='/opt/meshviewer_geojson_git' 4 | 5 | if [ ! -d "$MAP_GIT" ]; then 6 | echo "${MAP_GIT} does not exists!" >&2 7 | exit 1 8 | fi 9 | 10 | git -C "$MAP_GIT" pull 11 | if jq . "$MAP_GIT/{{meshviewer_geojson_file}}"; then 12 | cp "$MAP_GIT/{{meshviewer_geojson_file}}" "{{meshviewer_geojson_file_path}}/meshviewer.geojson" 13 | fi 14 | -------------------------------------------------------------------------------- /roles/meshviewer/templates/geojson.cronjob: -------------------------------------------------------------------------------- 1 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 2 | */5 * * * * root /usr/local/bin/geojson-update 3 | -------------------------------------------------------------------------------- /roles/monitoring-client/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | main_bridge: "br-{{ site_code }}" 3 | cmk_version: 2.2.0p30 4 | cmk_url: 'https://monitoring.bremen.freifunk.net/ffhb' 5 | cmk_plugins: 6 | - name: mk_filehandler 7 | - name: mk_sshd_config 8 | - name: mk_apt 9 | interval: 3600 10 | - name: mk_inventory.linux 11 | interval: 3600 12 | - name: admins 13 | local: true 14 | - name: systemtime 15 | local: true 16 | - name: lsbrelease 17 | local: true 18 | - name: fail2ban 19 | local: true 20 | - name: smart 21 | include: '{{ ansible_virtualization_role != "guest" }}' 22 | - name: unbound 23 | local: true 24 | include: "{{ (('vpnservers' in group_names) or ('vpnservers_legacy' in group_names)) }}" 25 | cmk_mrpe_checks: 26 | - name: conntrack 27 | command: /usr/local/lib/nagios/plugins/check_conntrack.sh 80 90 28 | include: "{{ (('vpnservers' in group_names) or ('vpnservers_legacy' in group_names)) }}" 29 | - name: dhcp 30 | command: /usr/lib/nagios/plugins/check_dhcp -i {{ main_bridge }} -u -s {{ batman_ipv4.address }} -t 5 31 | include: "{{ (('vpnservers' in group_names) or ('vpnservers_legacy' in group_names)) }}" 32 | - name: needrestart 33 | command: /usr/sbin/needrestart -p 34 | interval: 3600 35 | - name: etckeeper 36 | command: /usr/local/lib/nagios/plugins/check_git_status /etc 37 | -------------------------------------------------------------------------------- /roles/monitoring-client/files/98mk-apt: -------------------------------------------------------------------------------- 1 | # 2 | # retrigger mk-apt 3 | # 4 | # If you want use this hook, copy this file to: 5 | # /etc/apt/apt.conf.d/98mk-apt. 6 | # 7 | # For further details please consult the check manual page of apt. 8 | 9 | DPkg::Post-Invoke {"touch -t 197012181200 /var/lib/check_mk_agent/cache/*mk_apt.cache"; }; 10 | -------------------------------------------------------------------------------- /roles/monitoring-client/files/authorized_keys: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDJt2JopyozJi6md8wKlK5DNwmMVy7q+Si9x9I7xBWzhYEZjhlIRR13pWzDgxsE/ETEgRld5j1Tv20Tqfx4vGCRLKTqvYWXLczC5f59RnFCDcSnGTWh/lJKRRY0spEqAhn+jEp3U4wGE+bXw+oPt127E6HcItqz0zhd5RdiA3auC5UkG1xKnza1Eh/+E+obdkswSQoe3A2tOO5rF3m4/K4O/CzHL0iJytmduwy8sNL1RO5adEu72HSrCn/xKTRtvfHS5CXxpPk4qBtCc/N7TrGX734bGiljgPlIBmGbfFzpDAARaC87YWKMmwCoOG4PN8ZY169gzrsnIMZvQUWQ5ao2eZ7XFpn+7MwgXKG+5Bf21dm1iYygHJqRwwhsf50d+p3e0lzPSLCybiE88DBG0SlJ8iWuBbWFmPCaigUHj2AlMopjsSspIoTUHHNByH3gCP4WU0ZjGMtjlhm31vakAjVMvb/ZmmNhoZHGlEB0FwNdoImM+3TSwE0IKMF7khEK3/dpmOJ1kF7Q7Rce9002jEd1UB/rGYI/+d7ChJLyEiCS9dZqkJOADoY9dK3pOovUPQALj7+8QRqLGb0STE+Di+xP486vGDmG5a6WDQS9oBOxv8wuYlToocjvfxZb9hqLhssDmNHMUhdHi63XmLfR1cvWBSQmiYnNuEZ/R4q6ZBHy7w== Monitoring key of ffhb-monitoring 2 | -------------------------------------------------------------------------------- /roles/monitoring-client/files/plugins/check_git_status: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Copyright © 2010 by Daniel Friesel 4 | # License: WTFPL: 5 | # 0. You just DO WHAT THE FUCK YOU WANT TO. 6 | # 7 | # You probably need to run this check via sudo. For /etc, 8 | # > nagios ALL=(root) NOPASSWD: /usr/local/lib/nagios/plugins/check_git_status /etc 9 | # should do the job. 10 | 11 | declare -i STATE_OK=0 12 | declare -i STATE_WARNING=1 13 | declare -i STATE_CRITICAL=2 14 | declare -i STATE_UNKNOWN=3 15 | 16 | GIT="/usr/bin/git" 17 | 18 | REPO="${1}" 19 | 20 | if [ ! -x ${GIT} ]; then 21 | echo "Can't execute ${GIT}" 22 | exit $STATE_UNKNOWN 23 | fi 24 | 25 | if [ $# -lt 1 ]; then 26 | echo "Usage: $0 " 27 | exit $STATE_UNKNOWN 28 | fi 29 | 30 | if [ -z "${REPO}/.git" -o ! -d "${REPO}/.git" ]; then 31 | echo "No repo specified or ${REPO} is not a git repo" 32 | exit $STATE_UNKNOWN 33 | fi 34 | 35 | cd "${REPO}" || exit $STATE_UNKNOWN 36 | 37 | if [ -z "$(${GIT} ls-files --modified --deleted --others --exclude-standard)" ]; then 38 | echo "No uncommited changes in ${REPO}" 39 | exit $STATE_OK 40 | else 41 | echo "Uncommited changes in ${REPO}" 42 | exit $STATE_WARNING 43 | fi 44 | 45 | echo "Someting went wrong" 46 | exit $STATE_UNKNOWN 47 | -------------------------------------------------------------------------------- /roles/monitoring-client/files/plugins/check_rkhunter: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | declare -i STATE_OK=0 4 | declare -i STATE_WARNING=1 5 | declare -i STATE_CRITICAL=2 6 | declare -i STATE_UNKNOWN=3 7 | 8 | if [ ! -f /etc/rkhunter.conf ]; then 9 | ERR_MSG="rkhunter.conf not found. So probably rkhunter is not installed!" 10 | ERR_CODE=$STATE_CRITICAL 11 | else 12 | ERR_MSG="rkhunter.conf found. So rkhunter is installed." 13 | ERR_CODE=$STATE_OK 14 | fi 15 | 16 | if [ $ERR_CODE -eq $STATE_OK ]; then 17 | echo "OK: $ERR_MSG" 18 | else 19 | echo "ERROR: $ERR_MSG" 20 | fi 21 | 22 | exit $ERR_CODE 23 | -------------------------------------------------------------------------------- /roles/monitoring-client/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | -------------------------------------------------------------------------------- /roles/motd/files/add-motd-tail: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | if [ -e /etc/motd.tail ]; then 4 | cat /etc/motd.tail 5 | fi 6 | -------------------------------------------------------------------------------- /roles/motd/files/figlet: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | /usr/bin/figlet $(hostname) 4 | -------------------------------------------------------------------------------- /roles/motd/files/remove-motd-dynamic: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | if [ -e /var/run/motd.dynamic ]; then 4 | rm /var/run/motd.dynamic 5 | fi 6 | -------------------------------------------------------------------------------- /roles/motd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install figlet 3 | apt: 4 | name: figlet 5 | 6 | - name: Create /etc/update-motd.d 7 | file: 8 | path: /etc/update-motd.d 9 | state: directory 10 | mode: 0755 11 | owner: root 12 | group: root 13 | 14 | - name: Copy script to create hostname banner 15 | copy: 16 | src: figlet 17 | dest: /etc/update-motd.d/10figlet 18 | owner: root 19 | group: root 20 | mode: 0755 21 | 22 | - name: Copy script to remove /var/run/motd.dynamic 23 | copy: 24 | src: remove-motd-dynamic 25 | dest: /etc/update-motd.d/20remove-motd-dynamic 26 | owner: root 27 | group: root 28 | mode: 0755 29 | 30 | - name: Copy script to add motd.tail to motd 31 | copy: 32 | src: add-motd-tail 33 | dest: /etc/update-motd.d/30add-motd-tail 34 | owner: root 35 | group: root 36 | mode: 0755 37 | 38 | - name: Create symlink 39 | file: 40 | src: /run/motd 41 | dest: /etc/motd 42 | state: link 43 | force: yes 44 | -------------------------------------------------------------------------------- /roles/mysql-server/README.md: -------------------------------------------------------------------------------- 1 | mysql-server 2 | ========================= 3 | 4 | Installs MySQL server 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - mysql-server 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/mysql-server/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart mysql 3 | service: 4 | name: mysql 5 | state: restarted 6 | -------------------------------------------------------------------------------- /roles/mysql-server/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/mysql-server/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install MySQL server 3 | apt: 4 | name: mariadb-server 5 | 6 | - name: Increase max_allowed_packet setting 7 | lineinfile: 8 | dest: /etc/mysql/mariadb.conf.d/50-server.cnf 9 | regexp: '^\s*max_allowed_packet\s*=' 10 | line: 'max_allowed_packet = 32M' 11 | notify: restart mysql 12 | -------------------------------------------------------------------------------- /roles/nginx/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p tcp --dport 80 -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install nginx with Lua 3 | apt: 4 | name: 5 | - nginx-light 6 | - libnginx-mod-http-lua 7 | 8 | - name: Open firewall for nginx 9 | copy: 10 | src: firewall.sh 11 | dest: "{{ firewall_path }}/30-nginx" 12 | mode: 0644 13 | owner: root 14 | group: root 15 | when: firewall_enabled 16 | notify: reload firewall 17 | -------------------------------------------------------------------------------- /roles/nodejs/README.md: -------------------------------------------------------------------------------- 1 | nodejs 2 | ========================= 3 | 4 | Install nodejs from 5 | Repository 6 | 7 | 8 | Usage 9 | ------------------------- 10 | 11 | - hosts: servers 12 | roles: 13 | - nodejs 14 | 15 | 16 | License 17 | ------------------------- 18 | 19 | GPLv3 20 | -------------------------------------------------------------------------------- /roles/nodejs/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/nodejs/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Fetch APT repository key 3 | apt_key: 4 | url: 'https://deb.nodesource.com/gpgkey/nodesource.gpg.key' 5 | state: present 6 | 7 | - name: Install the Node.js APT repository 8 | apt_repository: 9 | repo: "deb https://deb.nodesource.com/node_14.x {{ ansible_distribution_release }} main" 10 | 11 | - name: Install Node.js 12 | apt: 13 | name: nodejs 14 | -------------------------------------------------------------------------------- /roles/nodemon/README.md: -------------------------------------------------------------------------------- 1 | nodemon 2 | ========================= 3 | 4 | Installing nodemon 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - nodemon 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/nodemon/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nodemon_email: 'nodemon@bremen.freifunk.net' 3 | nodemon_user: 'nodemon' 4 | nodemon_group: 'nodemon' 5 | nodemon_subdomain: 'nodemon' 6 | nodemon_domain: '{{ nodemon_subdomain }}.{{ main_domain }}' 7 | nodemon_git_root: 'https://github.com/FreifunkBremen/nodemon.git' 8 | nodemon_git_version: 'v0.2' 9 | -------------------------------------------------------------------------------- /roles/nodemon/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install dependencies 3 | command: 4 | cmd: /usr/bin/composer install 5 | chdir: /var/www/{{ nodemon_user }}/domains/{{ nodemon_domain }} 6 | become: yes 7 | become_user: "{{ nodemon_user }}" 8 | -------------------------------------------------------------------------------- /roles/nodemon/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - sudo 4 | - apache 5 | - letsencrypt 6 | - php 7 | - git 8 | galaxy_info: 9 | platforms: 10 | - name: Debian 11 | versions: 12 | - jessie 13 | -------------------------------------------------------------------------------- /roles/nodemon/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ nodemon_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ nodemon_subdomain }}.{{ alt_domain }} 6 | 7 | # Enable HTTPS proxying 8 | SSLProxyEngine On 9 | 10 | # Don't add header to proxy 11 | ProxyAddHeaders Off 12 | 13 | # set this to customers mail address 14 | ServerAdmin {{ nodemon_email }} 15 | 16 | SuexecUserGroup {{ nodemon_user }} {{ nodemon_group }} 17 | 18 | DocumentRoot /var/www/{{ nodemon_user }}/domains/{{ nodemon_domain }} 19 | 20 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 21 | Options +SymLinksIfOwnerMatch -Includes 22 | 23 | 24 | Alias /icons /usr/share/apache2/icons 25 | ScriptAlias /cgi-bin /var/www/{{ nodemon_user }}/cgi-bin 26 | ScriptAlias /fcgi-bin /var/www/{{ nodemon_user }}/fcgi-bin 27 | Include /etc/apache2/user-php-exec.conf 28 | 29 | ErrorLog /var/log/apache2/{{ nodemon_user }}/{{ nodemon_domain }}-error.log 30 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 31 | 32 | SSLEngine on 33 | SSLCertificateFile /etc/letsencrypt/certs/{{ nodemon_domain }}/fullchain.pem 34 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ nodemon_domain }}/privkey.pem 35 | 36 | -------------------------------------------------------------------------------- /roles/nodemon/templates/php-fcgi-starter: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # Set safe path 4 | export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 5 | 6 | # Set user environment 7 | export USER={{ nodemon_user }} 8 | export HOME=/home/{{ nodemon_user }} 9 | 10 | PHP_FCGI_CHILDREN=0 11 | export PHP_FCGI_CHILDREN 12 | PHP_FCGI_MAX_REQUESTS=250 13 | export PHP_FCGI_MAX_REQUESTS 14 | exec php-cgi 15 | -------------------------------------------------------------------------------- /roles/non_persistent_logging/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart journald 3 | systemd: 4 | name: systemd-journald 5 | state: restarted 6 | -------------------------------------------------------------------------------- /roles/non_persistent_logging/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Remove syslog daemons 3 | apt: 4 | name: 5 | - busybox-syslogd 6 | - dsyslog 7 | - inetutils-syslogd 8 | - rsyslog 9 | - syslog-ng 10 | state: absent 11 | purge: yes 12 | 13 | - name: Disable persistent storage 14 | replace: 15 | dest: /etc/systemd/journald.conf 16 | regexp: '^\#?Storage=.*$' 17 | replace: 'Storage=volatile' 18 | mode: '0644' 19 | notify: 20 | - restart journald 21 | -------------------------------------------------------------------------------- /roles/nsd/README.md: -------------------------------------------------------------------------------- 1 | nsd 2 | ========================= 3 | 4 | Install and configure NSD 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - nsd 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/nsd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nsd_update_nodes: false 3 | dns_nsd_git_repo: 'https://github.com/FreifunkBremen/ffhb-dns/' 4 | dns_nsd_git_commit: '01b065797e13f77fcc02b1c80c11a7a541229f9b' 5 | -------------------------------------------------------------------------------- /roles/nsd/files/cronjob: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | /usr/local/bin/zonegen.py \ 4 | http://downloads.bremen.freifunk.net/data/v1/nodes.json \ 5 | --contact=noc.bremen.freifunk.net \ 6 | --prefix=2a06:8782:ffbb::/48 \ 7 | --nserver dns.bremen.freifunk.net ns2.afraid.org ns2.he.net \ 8 | --file=/var/lib/nsd/nodes.bremen.freifunk.net.zone || exit 9 | 10 | # TODO: fix me! we could auto generate this based on ipv6_global_network 11 | /usr/local/bin/zonegen.py \ 12 | http://downloads.bremen.freifunk.net/data/v1/nodes.json \ 13 | --contact=noc.bremen.freifunk.net \ 14 | --prefix=2a06:8782:ffbb:42::/64 \ 15 | --nserver dns.bremen.freifunk.net ns2.afraid.org ns2.he.net \ 16 | --file=/var/lib/nsd/2.4.0.0.b.b.f.f.2.8.7.8.6.0.a.2.ip6.arpa.zone --reverse nodes.ffhb.de. || exit 17 | 18 | /usr/local/bin/zonegen.py \ 19 | http://downloads.bremen.freifunk.net/data/v1/nodes.json \ 20 | --contact=noc.bremen.freifunk.net \ 21 | --prefix=2a06:8782:ffbb:1337::/64 \ 22 | --nserver dns.bremen.freifunk.net ns2.afraid.org ns2.he.net \ 23 | --file=/var/lib/nsd/7.3.3.1.b.b.f.f.2.8.7.8.6.0.a.2.ip6.arpa.zone --reverse nodes.ffhb.de. || exit 24 | 25 | /usr/local/bin/zonegen.py \ 26 | http://downloads.bremen.freifunk.net/data/v1/nodes.json \ 27 | --contact=noc.bremen.freifunk.net \ 28 | --prefix=2a06:8782:ffbb:bab0::/64 \ 29 | --nserver dns.bremen.freifunk.net ns2.afraid.org ns2.he.net \ 30 | --file=/var/lib/nsd/0.b.a.b.b.b.f.f.2.8.7.8.6.0.a.2.ip6.arpa.zone --reverse nodes.ffhb.de. || exit 31 | 32 | nsd-control reload > /dev/null 33 | -------------------------------------------------------------------------------- /roles/nsd/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p udp --dport 53 -j ACCEPT 2 | ipt -A INPUT -p tcp --dport 53 -j ACCEPT 3 | -------------------------------------------------------------------------------- /roles/nsd/files/update-dns-zones.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 4 | 5 | DNS_ZONES_FOLDER='/opt/ffhb/dns' 6 | 7 | # Check if DNS zones folder exists 8 | if [ ! -d "$DNS_ZONES_FOLDER" ]; then 9 | echo "${DNS_ZONES_FOLDER} does not exists!" >&2 10 | exit 1 11 | fi 12 | 13 | git -C "$DNS_ZONES_FOLDER" pull 14 | 15 | for DNS_ZONE in "${DNS_ZONES_FOLDER}/"*.zone; do 16 | if ! nsd-checkzone "$(basename "$DNS_ZONE" '.zone')" "$DNS_ZONE"; then 17 | continue 18 | fi 19 | 20 | cp "$DNS_ZONE" "/var/lib/nsd/" 21 | 22 | # Reload DNS server configuration 23 | nsd-control reconfig >/dev/null 24 | 25 | # Reload zone 26 | nsd-control reload "$(basename "$DNS_ZONE" '.zone')" 27 | 28 | # Notify slaves about changed zones 29 | nsd-control notify "$(basename "$DNS_ZONE" '.zone')" 30 | done 31 | -------------------------------------------------------------------------------- /roles/nsd/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart nsd 3 | service: 4 | name: nsd 5 | state: restarted 6 | 7 | - name: copy zone files 8 | command: /usr/local/sbin/update-dns-zones.sh 9 | -------------------------------------------------------------------------------- /roles/nsd/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | - git 5 | galaxy_info: 6 | platforms: 7 | - name: Debian 8 | versions: 9 | - wheezy 10 | - jessie 11 | -------------------------------------------------------------------------------- /roles/nsd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages 3 | apt: 4 | name: 5 | - nsd 6 | - python3 7 | 8 | - name: Configure NSD 9 | template: 10 | src: nsd.conf 11 | dest: /etc/nsd/nsd.conf 12 | mode: 0644 13 | owner: root 14 | group: root 15 | notify: restart nsd 16 | 17 | - name: Clone internal dns repo 18 | git: 19 | repo: "{{ dns_nsd_git_repo }}" 20 | dest: "/opt/{{ site_code }}/dns/" 21 | version: "{{ dns_nsd_git_commit }}" 22 | notify: copy zone files 23 | 24 | - name: Install script to copy zone files 25 | copy: 26 | src: update-dns-zones.sh 27 | dest: /usr/local/sbin/update-dns-zones.sh 28 | mode: 0755 29 | owner: root 30 | group: root 31 | 32 | - name: Install script to generate nodes zone 33 | copy: 34 | src: zonegen.py 35 | dest: /usr/local/bin/zonegen.py 36 | mode: 0755 37 | owner: root 38 | group: root 39 | 40 | - name: Install cronjob to generate nodes zone 41 | copy: 42 | src: cronjob 43 | dest: /etc/cron.hourly/zonegen 44 | mode: 0755 45 | owner: root 46 | group: root 47 | 48 | - name: Initially generate nodes zone 49 | command: 50 | cmd: /etc/cron.hourly/zonegen 51 | creates: /var/lib/nsd/nodes.bremen.freifunk.net.zone 52 | 53 | - name: Open firewall for DNS 54 | copy: 55 | src: firewall.sh 56 | dest: "{{ firewall_path }}/30-nsd" 57 | mode: 0644 58 | owner: root 59 | group: root 60 | when: firewall_enabled 61 | notify: reload firewall 62 | 63 | - name: Autostart NSD 64 | service: 65 | name: nsd 66 | enabled: yes 67 | -------------------------------------------------------------------------------- /roles/nsd/templates/nsd.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | server: 3 | hide-version: yes 4 | identity: "unidentified server" 5 | ip4-only: no 6 | ip6-only: no 7 | debug-mode: no 8 | pidfile: "/run/nsd.pid" 9 | zonesdir: "/var/lib/nsd" 10 | verbosity: 0 11 | 12 | pattern: 13 | name: default 14 | zonefile: "%s.zone" 15 | # dns.he.net 16 | notify: 216.218.130.2 NOKEY 17 | provide-xfr: 216.218.133.2 NOKEY 18 | provide-xfr: 2001:470:600::2 NOKEY 19 | # afraid.org 20 | notify: 69.65.50.192 NOKEY 21 | notify: 2001:1850:1:5:800::6b NOKEY 22 | notify: 69.65.50.223 NOKEY 23 | provide-xfr: 69.65.50.192 NOKEY 24 | provide-xfr: 2001:1850:1:5:800::6b NOKEY 25 | provide-xfr: 69.65.50.223 NOKEY 26 | 27 | zone: 28 | name: {{ dns_domain_freifunk_net }} 29 | include-pattern: default 30 | 31 | zone: 32 | name: nodes.{{ dns_domain_freifunk_net }} 33 | include-pattern: default 34 | 35 | zone: 36 | name: {{ site_code }}.de 37 | include-pattern: default 38 | zonefile: {{ dns_domain_freifunk_net }}.zone 39 | 40 | zone: 41 | name: nodes.{{ site_code }}.de 42 | include-pattern: default 43 | zonefile: nodes.{{ dns_domain_freifunk_net }}.zone 44 | 45 | zone: 46 | name: on{{ site_code }}.de 47 | include-pattern: default 48 | 49 | zone: 50 | name: 2.8.7.8.6.0.a.2.ip6.arpa 51 | include-pattern: default 52 | 53 | zone: 54 | name: 7.3.3.1.b.b.f.f.2.8.7.8.6.0.a.2.ip6.arpa 55 | include-pattern: default 56 | 57 | zone: 58 | name: 0.b.a.b.b.b.f.f.2.8.7.8.6.0.a.2.ip6.arpa 59 | include-pattern: default 60 | 61 | zone: 62 | name: 213.117.185.in-addr.arpa 63 | include-pattern: default 64 | -------------------------------------------------------------------------------- /roles/nullmailer/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nullmailer_remote_server: 'mail.bremen.freifunk.net' 3 | mail_root_target: 'server@bremen.freifunk.net' 4 | -------------------------------------------------------------------------------- /roles/nullmailer/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart nullmailer 3 | service: 4 | name: nullmailer 5 | state: restarted 6 | -------------------------------------------------------------------------------- /roles/nullmailer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install local mailserver 3 | apt: 4 | name: nullmailer 5 | 6 | - name: Copy nullmailer remote 7 | template: 8 | src: remotes 9 | dest: /etc/nullmailer/remotes 10 | mode: '0640' 11 | owner: root 12 | group: "{{ group }}" 13 | notify: restart nullmailer 14 | vars: 15 | group: "{{ (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') | ternary('mail', 'nullmail') }}" 16 | 17 | - name: Copy nullmailer adminaddr 18 | copy: 19 | dest: /etc/nullmailer/adminaddr 20 | content: "{{ mail_root_target }}\n" 21 | mode: 0644 22 | owner: root 23 | group: root 24 | notify: restart nullmailer 25 | -------------------------------------------------------------------------------- /roles/nullmailer/templates/remotes: -------------------------------------------------------------------------------- 1 | {{ nullmailer_remote_server }} smtp{% if nullmailer_remote_user is defined %} --user={{ nullmailer_remote_user }} --pass={{ nullmailer_remote_password }}{% endif %} 2 | -------------------------------------------------------------------------------- /roles/openssh/README.md: -------------------------------------------------------------------------------- 1 | openssh 2 | ========================= 3 | 4 | Some hardening for your OpenSSH daemon 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - openssh 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/openssh/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p tcp --dport 22 -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/openssh/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload ssh 3 | service: 4 | name: ssh 5 | state: reloaded 6 | -------------------------------------------------------------------------------- /roles/openssh/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/openssh/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Update SSH configuration 3 | replace: 4 | path: /etc/ssh/sshd_config 5 | regexp: '^([\#\s]*)?{{ item.key }}\s+([\w_-]+)' 6 | replace: "{{ item.key }} {{ item.value }}" 7 | backup: yes 8 | with_items: 9 | - key: PermitRootLogin 10 | value: without-password 11 | - key: PasswordAuthentication 12 | value: 'no' 13 | - key: ChallengeResponseAuthentication 14 | value: 'no' 15 | - key: PrintLastLog 16 | value: 'no' 17 | notify: 18 | - reload ssh 19 | 20 | - name: Open firewall for SSH 21 | copy: 22 | src: firewall.sh 23 | dest: "{{ firewall_path }}/10-ssh" 24 | mode: 0644 25 | owner: root 26 | group: root 27 | when: firewall_enabled 28 | notify: reload firewall 29 | -------------------------------------------------------------------------------- /roles/php/README.md: -------------------------------------------------------------------------------- 1 | PHP 2 | ========================= 3 | 4 | Installing PHP 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - php 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/php/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/php/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install PHP and needed modules 3 | apt: 4 | name: 5 | - composer 6 | - php7.4-cgi 7 | - php7.4-cli 8 | - php7.4-curl 9 | - php7.4-dev 10 | - php7.4-gd 11 | - php7.4-mysql 12 | - php7.4-sqlite3 13 | - php7.4-apcu 14 | -------------------------------------------------------------------------------- /roles/restic/README.md: -------------------------------------------------------------------------------- 1 | restic 2 | ========================= 3 | 4 | Install Restic backup tool 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - restic 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/restic/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | restic_version: 0.9.1 3 | restic_release_checksum: sha1:e65f3025db0ade9b7515da067a949b3d8b230a8a 4 | -------------------------------------------------------------------------------- /roles/restic/files/backup-restic.default: -------------------------------------------------------------------------------- 1 | EXCLUDES=('/dev' '/proc' '/sys' '/var/run' '/var/tmp' '/run' '/lost+found' '/mnt' '/tmp') 2 | TARGETS=() 3 | BACKUP_NICE=0 4 | BACKUP_PASSWORDS=() 5 | 6 | backup_prepare() { 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /roles/restic/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install restic 3 | apt: 4 | name: restic 5 | 6 | - name: Copy cronjob 7 | copy: 8 | src: backup-restic 9 | dest: /etc/cron.daily/backup-restic 10 | mode: 0755 11 | owner: root 12 | group: root 13 | 14 | - name: Copy configuration file 15 | copy: 16 | src: backup-restic.default 17 | dest: /etc/default/backup-restic 18 | mode: 0600 19 | owner: root 20 | group: root 21 | force: no 22 | -------------------------------------------------------------------------------- /roles/rkhunter/README.md: -------------------------------------------------------------------------------- 1 | rkhunter 2 | ========================= 3 | 4 | Installs rkhunter 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - rkhunter 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/rkhunter/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/router-bird/README.md: -------------------------------------------------------------------------------- 1 | router-bird 2 | ========================= 3 | 4 | Install bird 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - router-bird 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/router-bird/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ffhb_routing_table: default-freifunk 3 | -------------------------------------------------------------------------------- /roles/router-bird/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload bird 3 | service: 4 | name: bird 5 | state: reloaded 6 | 7 | - name: reload bird6 8 | service: 9 | name: bird6 10 | state: reloaded 11 | -------------------------------------------------------------------------------- /roles/router-bird/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | -------------------------------------------------------------------------------- /roles/router-bird/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install bird 3 | apt: 4 | name: bird 5 | 6 | - name: Create directories for extra config snippets 7 | file: 8 | dest: "/etc/bird/{{ item }}" 9 | state: directory 10 | mode: 0755 11 | owner: root 12 | group: root 13 | with_items: 14 | - bird.conf.d 15 | - bird6.conf.d 16 | 17 | - name: Install config templates 18 | template: 19 | src: "{{ item }}" 20 | dest: "/etc/bird/{{ item }}" 21 | mode: 0644 22 | owner: root 23 | group: root 24 | with_items: 25 | - bird.conf 26 | - bird6.conf 27 | notify: 28 | - reload bird 29 | - reload bird6 30 | 31 | - name: Install internal ipv4 config templates 32 | template: 33 | src: internal_ipv4.conf 34 | dest: /etc/bird/bird.conf.d/internal.conf 35 | mode: 0644 36 | owner: root 37 | group: root 38 | notify: 39 | - reload bird 40 | 41 | - name: Install internal ipv6 config templates 42 | template: 43 | src: internal_ipv6.conf 44 | dest: /etc/bird/bird6.conf.d/internal.conf 45 | mode: 0644 46 | owner: root 47 | group: root 48 | notify: 49 | - reload bird6 50 | 51 | - name: Open firewall for BGP 52 | template: 53 | src: firewall.sh 54 | dest: "{{ firewall_path }}/30-bird" 55 | mode: 0644 56 | owner: root 57 | group: root 58 | when: firewall_enabled 59 | notify: reload firewall 60 | 61 | - name: Start bird 62 | service: 63 | name: "{{ item }}" 64 | state: started 65 | enabled: yes 66 | with_items: 67 | - bird 68 | - bird6 69 | -------------------------------------------------------------------------------- /roles/router-bird/templates/bird.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | table ebgp; 3 | 4 | define ownas = {{ icvpn_as }}; 5 | 6 | router id {{ batman_ipv4.address }}; 7 | 8 | ### functions ### 9 | 10 | # own network 11 | function is_self_net() { 12 | return net ~ [ 13 | 10.196.0.0/16+ 14 | ]; 15 | }; 16 | 17 | # freifunk ip ranges in general 18 | function is_freifunk() { 19 | return net ~ [ 20 | 10.0.0.0/8+, 21 | 104.0.0.0/8+ 22 | ]; 23 | }; 24 | 25 | # dn42 ip ranges 26 | function is_dn42() { 27 | return net ~ [ 28 | 172.22.0.0/15{16,32} 29 | ]; 30 | }; 31 | 32 | ### kernel ### 33 | 34 | protocol kernel k_frei { 35 | scan time 10; 36 | kernel table 252; 37 | import none; 38 | export filter { 39 | krt_prefsrc = {{ batman_ipv4.address }}; 40 | accept; 41 | }; 42 | }; 43 | 44 | # this pseudo-protocol watches all interface up/down events 45 | protocol device { 46 | scan time 10; 47 | }; 48 | 49 | ### pipes ### 50 | 51 | protocol pipe p_maintbl { 52 | peer table ebgp; 53 | import all; 54 | export none; 55 | }; 56 | 57 | ### static routes ### 58 | 59 | # create a super route for own freifunk net in ebgp table 60 | protocol static static_{{ site_code }} { 61 | table ebgp; 62 | route 10.196.0.0/16 reject; 63 | }; 64 | 65 | ### templates ### 66 | 67 | template bgp icvpn { 68 | local as ownas; 69 | table ebgp; 70 | import where ((is_freifunk() || is_dn42()) && !is_self_net()); 71 | export where is_freifunk() || is_dn42() || is_self_net(); 72 | }; 73 | 74 | template bgp dn42 from icvpn { 75 | import where is_dn42() && !is_self_net(); 76 | export where is_freifunk() || is_dn42() || is_self_net(); 77 | }; 78 | 79 | template bgp internal from icvpn { 80 | import filter { 81 | bgp_path.prepend(ownas); 82 | if ((is_freifunk() || is_dn42()) && !is_self_net()) then accept; 83 | else reject; 84 | }; 85 | direct; 86 | }; 87 | 88 | ### include extra config files ### 89 | include "/etc/bird/bird.conf.d/*.conf"; 90 | -------------------------------------------------------------------------------- /roles/router-bird/templates/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -i '{{ main_bridge }}' -p tcp --dport 179 -j ACCEPT 2 | -------------------------------------------------------------------------------- /roles/router-bird/templates/internal_ipv4.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | {% for host in group %} 3 | {% if hostvars[host]['vpn_id'] != vpn_id %} 4 | protocol bgp {{ site_vpn_prefix }}{{ "%02d" % hostvars[host]['vpn_id'] }} from internal { 5 | neighbor {{ hostvars[host]['batman_ipv4']['address'] }} as ownas; 6 | }; 7 | {% endif %} 8 | {% endfor %} 9 | -------------------------------------------------------------------------------- /roles/router-bird/templates/internal_ipv6.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | {% for host in group %} 3 | {% if hostvars[host]['vpn_id'] != vpn_id %} 4 | protocol bgp {{ site_vpn_prefix }}{{ "%02d" % hostvars[host]['vpn_id'] }} from internal { 5 | neighbor {{ hostvars[host]['batman_ipv6_local']['address'] }} as ownas; 6 | }; 7 | {% endif %} 8 | {% endfor %} 9 | -------------------------------------------------------------------------------- /roles/router-bird/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | group: "{{ ('vpnservers' in group_names) | ternary(groups['vpnservers'], groups['vpnservers_legacy']) }}" 3 | ipv6_global_address: "{{ batman_ipv6_global.address }}/{{ batman_ipv6_global.size }}" 4 | ipv6_local_address: "{{ batman_ipv6_local.address }}/{{ batman_ipv6_local.size }}" 5 | -------------------------------------------------------------------------------- /roles/ruby/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Ruby 3 | apt: 4 | name: 5 | - build-essential 6 | - bundler 7 | - libsqlite3-dev 8 | - ruby 9 | - ruby-dev 10 | - ruby-i18n 11 | -------------------------------------------------------------------------------- /roles/speedtest/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | speedtest_git_root: 'https://github.com/adolfintel/speedtest.git' 3 | speedtest_git_commit: 'bf696d8da26a1c5f9d8dec925ad1ed01d7a1bb35' 4 | -------------------------------------------------------------------------------- /roles/speedtest/files/nginx.conf: -------------------------------------------------------------------------------- 1 | location /speedtest/ { 2 | add_header Access-Control-Allow-Origin "*"; 3 | add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0"; 4 | add_header Cache-Control "post-check=0, pre-check=0"; 5 | add_header Pragma no-cache; 6 | 7 | location /speedtest/empty { 8 | return 200; 9 | } 10 | 11 | location /speedtest/getIP { 12 | default_type 'text/plain'; 13 | content_by_lua_block { 14 | ngx.print(ngx.var.remote_addr); 15 | } 16 | } 17 | 18 | location /speedtest/garbage { 19 | default_type 'application/octet-stream'; 20 | add_header Access-Control-Allow-Origin "*"; 21 | add_header Content-Disposition "attachment; filename=random.dat"; 22 | add_header Content-Transer-Encoding binary; 23 | add_header Content-Description "File Transfer"; 24 | add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0"; 25 | add_header Cache-Control "post-check=0, pre-check=0"; 26 | add_header Pragma no-cache; 27 | content_by_lua_block { 28 | local urandom = io.open('/dev/urandom', 'r') 29 | local rand = urandom:read(1048576) 30 | local chunks = (ngx.var.arg_ckSize or 4) * 1 31 | 32 | while chunks > 0 do 33 | ngx.print(rand) 34 | ngx.flush() 35 | chunks = chunks - 1 36 | end 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /roles/speedtest/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy nginx config 3 | copy: 4 | src: nginx.conf 5 | dest: /etc/nginx/snippets/speedtest.conf 6 | mode: 0644 7 | owner: root 8 | group: root 9 | 10 | - name: Configure nginx default vHost 11 | lineinfile: # noqa no-tabs 12 | path: /etc/nginx/sites-available/default 13 | line: " include snippets/speedtest.conf;" 14 | insertafter: "server_name _;" 15 | 16 | - name: Clone HTML5 speedtest repo 17 | git: 18 | repo: "{{ speedtest_git_root }}" 19 | dest: '/var/www/html/speedtest' 20 | version: "{{ speedtest_git_commit }}" 21 | 22 | - name: Create symlink for index.html 23 | file: 24 | path: /var/www/html/speedtest/index.html 25 | state: link 26 | src: example-gauges.html 27 | -------------------------------------------------------------------------------- /roles/sudo/README.md: -------------------------------------------------------------------------------- 1 | sudo 2 | ========================= 3 | 4 | Install sudo 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - sudo 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/sudo/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | platforms: 4 | - name: Debian 5 | versions: 6 | - wheezy 7 | - jessie 8 | -------------------------------------------------------------------------------- /roles/sudo/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install sudo 3 | apt: 4 | name: sudo 5 | -------------------------------------------------------------------------------- /roles/system/README.md: -------------------------------------------------------------------------------- 1 | system 2 | ========================= 3 | 4 | Install sysctl files 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - system 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/system/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | hostname: defaulthost 3 | reboot_flag: false 4 | -------------------------------------------------------------------------------- /roles/system/files/autologin.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | ExecStart= 3 | ExecStart=-/sbin/agetty -p -a root --keep-baud 115200,57600,38400,9600 %I $TERM 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/dmesg-restrict.conf: -------------------------------------------------------------------------------- 1 | kernel.dmesg_restrict = 1 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/fs-file-max.conf: -------------------------------------------------------------------------------- 1 | # increase system file descriptor limit 2 | fs.file-max = 65535 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-arp-ignore.conf: -------------------------------------------------------------------------------- 1 | # only announce corresponding IP addresses on other interfaces 2 | net.ipv4.conf.default.arp_ignore=1 3 | net.ipv4.conf.all.arp_ignore=1 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-forwarding.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.conf.all.forwarding=1 2 | net.ipv4.conf.default.forwarding=1 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-icmp-errors-use-inbound-ifaddr.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.icmp_errors_use_inbound_ifaddr = 1 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-ignore-icmp-bogus-error-responses.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.icmp_ignore_bogus_error_responses=0 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-ignore-icmp-broadcast.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.icmp_echo_ignore_broadcasts=1 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-tcp-abort-on-overflow.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.tcp_abort_on_overflow=1 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-tcp-fin-timeout.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.tcp_fin_timeout=30 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-tcp-syn-retries.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.tcp_syn_retries=3 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-tcp-synack-retries.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.tcp_synack_retries=3 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv4-tcp-syncookies.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.tcp_syncookies=1 2 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/ipv6-forwarding.conf: -------------------------------------------------------------------------------- 1 | net.ipv6.conf.all.forwarding=1 2 | net.ipv6.conf.default.forwarding=1 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/kernel-core-uses-pid.conf: -------------------------------------------------------------------------------- 1 | # Controls whether core dumps will append the PID to the core filename 2 | # Useful for debugging multi-threaded applications 3 | kernel.core_uses_pid = 1 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/kernel-panic.conf: -------------------------------------------------------------------------------- 1 | # Auto-reboot linux 30 seconds after a kernel panic 2 | kernel.panic = 30 3 | kernel.panic_on_oops = 30 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/kernel-pid-max.conf: -------------------------------------------------------------------------------- 1 | # Allow for more PIDs 2 | kernel.pid_max = 65536 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/kernel-shm.conf: -------------------------------------------------------------------------------- 1 | # Set maximum amount of memory allocated to shm to 256MB 2 | kernel.shmmax = 67108864 3 | kernel.shmall = 67108864 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/kernel-sysrq.conf: -------------------------------------------------------------------------------- 1 | # Controls the System Request debugging functionality of the kernel 2 | kernel.sysrq = 0 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/no-ipv4-redirects.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.conf.all.send_redirects=0 2 | net.ipv4.conf.default.send_redirects=0 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/no-ipv4-rp-filter.conf: -------------------------------------------------------------------------------- 1 | net.ipv4.conf.all.rp_filter=0 2 | net.ipv4.conf.default.rp_filter=0 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/no-ipv6.conf: -------------------------------------------------------------------------------- 1 | net.ipv6.conf.all.autoconf=0 2 | net.ipv6.conf.all.accept_ra=0 3 | net.ipv6.conf.default.autoconf=0 4 | net.ipv6.conf.default.accept_ra=0 5 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/vm-min-free-kbytes.conf: -------------------------------------------------------------------------------- 1 | # Keep at least 64MB of free RAM space available 2 | vm.min_free_kbytes = 65536 3 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/vm-overcommit.conf: -------------------------------------------------------------------------------- 1 | # No overcommitment of available memory 2 | vm.overcommit_ratio = 0 3 | vm.overcommit_memory = 0 4 | -------------------------------------------------------------------------------- /roles/system/files/sysctl.d/vm-swappiness.conf: -------------------------------------------------------------------------------- 1 | vm.swappiness = 0 2 | -------------------------------------------------------------------------------- /roles/system/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload sysctl 3 | command: /sbin/sysctl --system 4 | 5 | - name: update grub 6 | command: update-grub 7 | 8 | - name: restart systemd-logind 9 | systemd: 10 | name: systemd-logind 11 | state: restarted 12 | -------------------------------------------------------------------------------- /roles/system/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Installing sysctl.d configs 3 | copy: 4 | src: sysctl.d/ 5 | dest: /etc/sysctl.d/ 6 | mode: 0644 7 | owner: root 8 | group: root 9 | notify: reload sysctl 10 | 11 | - name: Load modules needed for sysctl configs early 12 | lineinfile: 13 | dest: /etc/modules 14 | line: nf_conntrack 15 | regexp: '^nf_conntrack' 16 | 17 | - name: Setting hostname 18 | hostname: 19 | name: "{{ hostname }}" 20 | when: hostname != 'defaulthost' 21 | 22 | - name: Make boot non-quiet 23 | lineinfile: 24 | path: /etc/default/grub 25 | regexp: '^#?GRUB_CMDLINE_LINUX_DEFAULT=' 26 | line: 'GRUB_CMDLINE_LINUX_DEFAULT=""' 27 | notify: update grub 28 | 29 | - name: Detect serial devices 30 | slurp: 31 | src: /proc/tty/driver/serial 32 | register: system_serial_devices 33 | 34 | - name: Parse serial devices 35 | set_fact: 36 | serial_devices: "{{ system_serial_devices.content | b64decode | split('\n') | reject('search', 'serinfo:|uart:unknown|^$') | map('split', ': ') | map(attribute=0) | list }}" 37 | 38 | - name: Enable serial console in GRUB and Linux console 39 | template: 40 | src: grub-serial.cfg 41 | dest: /etc/default/grub.d/serial.cfg 42 | mode: '0644' 43 | notify: update grub 44 | when: 'serial_devices | length > 0' 45 | 46 | - name: Enable serial getty 47 | systemd: 48 | name: 'serial-getty@ttyS{{ item }}.service' 49 | state: started 50 | enabled: yes 51 | loop: "{{ serial_devices }}" 52 | 53 | - name: Configure VM 54 | include_tasks: vm.yml 55 | when: ansible_virtualization_role == "guest" 56 | 57 | - name: Reboot host 58 | command: reboot 59 | when: reboot_flag 60 | -------------------------------------------------------------------------------- /roles/system/tasks/vm.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Optimize kernel parameters for VMs 3 | lineinfile: 4 | path: /etc/default/grub 5 | regexp: '^#?GRUB_CMDLINE_LINUX=' 6 | line: 'GRUB_CMDLINE_LINUX="elevator=noop nohz=on consoleblank=0"' 7 | notify: update grub 8 | when: 'ansible_virtualization_role | default == "guest"' 9 | 10 | - name: Enable autologin on serial terminal 11 | copy: 12 | dest: /etc/systemd/system/serial-getty@.service.d/ 13 | src: autologin.conf 14 | 15 | - name: Install packages 16 | apt: 17 | name: 18 | - dbus # for systemd-logind 19 | - qemu-guest-agent 20 | notify: restart systemd-logind 21 | 22 | - name: Let systemd-logind handle power button 23 | lineinfile: 24 | path: /etc/systemd/logind.conf 25 | regexp: '^#?HandlePowerKey=' 26 | line: 'HandlePowerKey=poweroff' 27 | notify: restart systemd-logind 28 | 29 | - name: Install cloud kernel 30 | apt: 31 | name: linux-image-cloud-amd64 32 | when: 33 | - '"backbone" not in group_names' 34 | - '"ffmapserver" not in group_names' 35 | - '"bgp-" not in inventory_hostname' 36 | 37 | - name: Uninstall non-cloud kernel 38 | apt: 39 | name: linux-image-amd64 40 | state: absent 41 | purge: yes 42 | when: 43 | - '"backbone" not in group_names' 44 | - '"ffmapserver" not in group_names' 45 | - '"bgp-" not in inventory_hostname' 46 | -------------------------------------------------------------------------------- /roles/system/templates/grub-serial.cfg: -------------------------------------------------------------------------------- 1 | GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} console=tty0 console=ttyS{{ serial_devices[-1] }},115200n8" 2 | GRUB_TERMINAL=serial 3 | GRUB_SERIAL_COMMAND="serial --unit={{ serial_devices[-1] }} --speed=115200 --word=8 --parity=no --stop=1" 4 | -------------------------------------------------------------------------------- /roles/tasksite/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | tasks_email: 'info@bremen.freifunk.net' 3 | tasks_user: 'tasks' 4 | tasks_group: 'tasks' 5 | tasks_subdomain: 'tasks' 6 | tasks_domain: '{{ tasks_subdomain }}.{{ main_domain }}' 7 | -------------------------------------------------------------------------------- /roles/tasksite/files/htaccess: -------------------------------------------------------------------------------- 1 | RewriteRule ^/rsrc/(.*) - [L,QSA] 2 | RewriteRule ^/favicon.ico - [L,QSA] 3 | RewriteRule ^(.*)$ index.php?__path__=/$1 [B,L,QSA] 4 | -------------------------------------------------------------------------------- /roles/tasksite/files/run-log: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | exec multilog t ./main 3 | -------------------------------------------------------------------------------- /roles/tasksite/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - apt 4 | - sudo 5 | - tools 6 | - apache 7 | - letsencrypt 8 | - php 9 | - git 10 | - mysql-server 11 | galaxy_info: 12 | platforms: 13 | - name: Debian 14 | versions: 15 | - jessie 16 | -------------------------------------------------------------------------------- /roles/tasksite/templates/apache-tasks.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ tasks_subdomain }}.{{ alt_domain }} 5 | 6 | # Don't add header to proxy 7 | ProxyAddHeaders Off 8 | 9 | # set this to customers mail address 10 | ServerAdmin {{ tasks_email }} 11 | 12 | SuexecUserGroup {{ tasks_user }} {{ tasks_group }} 13 | 14 | DocumentRoot /var/www/{{ tasks_user }}/domains/{{ tasks_domain }} 15 | 16 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 17 | Options +SymLinksIfOwnerMatch -Includes 18 | 19 | 20 | ScriptAlias /cgi-bin /var/www/tasks/cgi-bin 21 | ScriptAlias /fcgi-bin /var/www/tasks/fcgi-bin 22 | Include /etc/apache2/user-php-exec.conf 23 | 24 | FcgidMaxRequestLen 16777216 25 | FcgidPassHeader Authorization 26 | 27 | RewriteEngine on 28 | RewriteOptions inherit 29 | 30 | ErrorLog /var/log/apache2/{{ tasks_user }}/default-error.log 31 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 32 | 33 | SSLEngine on 34 | SSLCertificateFile /etc/letsencrypt/certs/{{ tasks_domain }}/fullchain.pem 35 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ tasks_domain }}/privkey.pem 36 | 37 | 38 | 39 | ServerName {{ tasks_subdomain }}.{{ main_domain }} 40 | 41 | RewriteEngine on 42 | RewriteOptions inherit 43 | 44 | RedirectMatch 301 (.*) https://{{ tasks_subdomain }}.{{ alt_domain }}$1 45 | 46 | ErrorLog /var/log/apache2/{{ tasks_user }}/default-error.log 47 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 48 | 49 | SSLEngine on 50 | SSLCertificateFile /etc/letsencrypt/certs/{{ tasks_domain }}/fullchain.pem 51 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ tasks_domain }}/privkey.pem 52 | 53 | -------------------------------------------------------------------------------- /roles/tasksite/templates/ffhb.conf.php: -------------------------------------------------------------------------------- 1 | 'localhost', 7 | 'mysql.user' => 'phabric', 8 | 'mysql.pass' => '{{ mysql_password_base64["content"] | b64decode }}', 9 | 'phabricator.timezone' => 'Europe/Berlin', 10 | # Phabricator only supports one single base URI, and we have used the shorter one (tasks.ffhb.de) so far: 11 | 'phabricator.base-uri' => 'https://{{ tasks_subdomain }}.{{ alt_domain }}/', 12 | 'repository.default-local-path' => '/home/{{ tasks_user }}/.var/repo', 13 | 'storage.local-disk.path' => '/home/{{ tasks_user }}/.var/storage', 14 | ); 15 | -------------------------------------------------------------------------------- /roles/tasksite/templates/phabricator-daemon-file: -------------------------------------------------------------------------------- 1 | { 2 | "daemonize": false, 3 | "daemons": [ 4 | { 5 | "class": "PhabricatorRepositoryPullLocalDaemon", 6 | "label": "PhabricatorRepositoryPullLocalDaemon" 7 | }, 8 | { 9 | "class": "PhabricatorTriggerDaemon", 10 | "label": "PhabricatorTriggerDaemon" 11 | }, 12 | { 13 | "class": "PhabricatorTaskmasterDaemon", 14 | "label": "PhabricatorTaskmasterDaemon" 15 | } 16 | ], 17 | "log": "/home/{{ tasks_user }}/.var/tmp/log/daemons.log", 18 | "piddir": "/home/{{ tasks_user }}/.var/tmp/pid" 19 | } 20 | -------------------------------------------------------------------------------- /roles/tasksite/templates/phabricator.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Phabricator project management system 3 | 4 | [Service] 5 | Environment=PHP_INI_SCAN_DIR=:%h/.config/etc/php 6 | Environment=INSTALL_ROOT=/var/www/{{ tasks_user }}/opt/phabricator 7 | Environment=PHD_TMP_DIR=%h/.var/tmp/phabricator 8 | SyslogIdentifier=%p 9 | ExecStartPre=/bin/mkdir -p ${PHD_TMP_DIR}/pid ${PHD_TMP_DIR}/log 10 | ExecStart=/bin/sh -c "exec /var/www/{{ tasks_user }}/opt/phabricator/phabricator/scripts/daemon/phd-daemon < .config/phabricator-daemon-file" 11 | 12 | [Install] 13 | WantedBy=default.target 14 | -------------------------------------------------------------------------------- /roles/tasksite/templates/php-extopts.ini: -------------------------------------------------------------------------------- 1 | ; {{ ansible_managed }} 2 | 3 | [PHP] 4 | post_max_size=32M 5 | 6 | [opcache] 7 | opcache.validate_timestamps=0 8 | -------------------------------------------------------------------------------- /roles/tasksite/templates/php-fcgi-starter: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # Set safe path 4 | export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 5 | 6 | # Set user environment 7 | export USER={{ tasks_user }} 8 | export HOME=/home/{{ tasks_user }} 9 | 10 | . $HOME/.local/bin/php_env.sh 11 | 12 | PHP_FCGI_CHILDREN=0 13 | export PHP_FCGI_CHILDREN 14 | PHP_FCGI_MAX_REQUESTS=250 15 | export PHP_FCGI_MAX_REQUESTS 16 | exec php-cgi 17 | -------------------------------------------------------------------------------- /roles/tiles/README.md: -------------------------------------------------------------------------------- 1 | tiles 2 | ===== 3 | 4 | Install tessera as a map tile server and configure Apache to cache its responses. 5 | 6 | 7 | Usage 8 | ----- 9 | 10 | - hosts: servers 11 | roles: 12 | - tiles 13 | 14 | 15 | License 16 | ------- 17 | 18 | BSD 19 | -------------------------------------------------------------------------------- /roles/tiles/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | tiles_email: 'info@bremen.freifunk.net' 3 | tiles_user: tiles 4 | tiles_group: tiles 5 | tiles_subdomain: tiles 6 | tiles_domain: '{{ tiles_subdomain }}.{{ main_domain }}' 7 | tiles_tessera_port: 63114 8 | tiles_git_root: 'https://github.com/FreifunkBremen/mapbox-studio-osm-bright.tm2.git' 9 | tiles_git_commit: 'a3c2b948b8816a492660f6ee7b1b9667d0c4df2e' 10 | -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-Light.ttf -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /roles/tiles/files/OpenSans/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/tiles/files/OpenSans/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /roles/tiles/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart tessera 3 | systemd: 4 | name: tessera.service 5 | scope: user 6 | state: restarted 7 | become: yes 8 | become_user: "{{ tiles_user }}" 9 | -------------------------------------------------------------------------------- /roles/tiles/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - apache 4 | - apt 5 | - git 6 | - letsencrypt 7 | - nodejs 8 | - ruby 9 | - sudo 10 | - tools 11 | galaxy_info: 12 | platforms: 13 | - name: Debian 14 | versions: 15 | - jessie 16 | -------------------------------------------------------------------------------- /roles/tiles/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ tiles_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ tiles_subdomain }}.{{ alt_domain }} 6 | 7 | # set this to customers mail address 8 | ServerAdmin {{ tiles_email }} 9 | 10 | ErrorLog /var/log/apache2/{{ tiles_user }}/default-error.log 11 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 12 | 13 | ProxyPass / http://127.0.0.1:{{ tiles_tessera_port }}/ 14 | 15 | # Don't add header to proxy 16 | ProxyAddHeaders Off 17 | 18 | # cache tiles for 7 days on disk, ignoring client refreshes 19 | CacheEnable disk / 20 | CacheDisable /.well-known/acme-challenge 21 | CacheDefaultExpire 604800 22 | CacheIgnoreCacheControl on 23 | CacheIgnoreQueryString on 24 | # this unifies the cache for HTTP and HTTPS 25 | CacheKeyBaseURL "http://{{ tiles_domain }}/" 26 | 27 | SSLEngine on 28 | SSLCertificateFile /etc/letsencrypt/certs/{{ tiles_domain }}/fullchain.pem 29 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ tiles_domain }}/privkey.pem 30 | 31 | -------------------------------------------------------------------------------- /roles/tiles/templates/tessera.service: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | [Unit] 4 | Description=Tessera map tile renderer 5 | 6 | [Service] 7 | Environment=MAPNIK_FONT_PATH=%h/.fonts PORT={{ tiles_tessera_port }} 8 | 9 | MemoryMax=2G 10 | SyslogIdentifier=%p 11 | ExecStart=%h/node_modules/tessera/bin/tessera.js -b 127.0.0.1 tmstyle://./mapbox-studio-osm-bright.tm2 12 | Restart=always 13 | RestartSec=5 14 | 15 | [Install] 16 | WantedBy=default.target 17 | -------------------------------------------------------------------------------- /roles/tmpfs/README.md: -------------------------------------------------------------------------------- 1 | tmpfs 2 | ========================= 3 | 4 | Enable tmpfs for /tmp 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - tmpfs 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/tmpfs/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy tmp.mount 3 | copy: 4 | src: /usr/share/systemd/tmp.mount 5 | dest: /etc/systemd/system/tmp.mount 6 | remote_src: yes 7 | 8 | - name: Enable tmpfs for /tmp 9 | systemd: 10 | daemon_reload: yes 11 | enabled: yes 12 | name: tmp.mount 13 | -------------------------------------------------------------------------------- /roles/tools/README.md: -------------------------------------------------------------------------------- 1 | tools 2 | ========================= 3 | 4 | Installing several useful tools 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - tools 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/tools/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install a bunch of helpful tools 3 | apt: 4 | name: 5 | - ca-certificates 6 | - curl 7 | - less 8 | - molly-guard 9 | - screen 10 | - tcpdump 11 | - tmux 12 | - zsh 13 | 14 | - name: Download .zshrc from grml 15 | get_url: 16 | url: https://raw.githubusercontent.com/grml/grml-etc-core/v0.12.5/etc/zsh/zshrc 17 | dest: /etc/zsh/zshrc 18 | checksum: sha256:ad88c76951693c2f9c38773ed2602a9fd5c74431615c4a23aaff679b295919ce 19 | validate_certs: false 20 | 21 | - name: Change shell for root 22 | user: 23 | name: root 24 | shell: /bin/zsh 25 | -------------------------------------------------------------------------------- /roles/unbound/README.md: -------------------------------------------------------------------------------- 1 | unbound 2 | ========================= 3 | 4 | Install and configure unbound 5 | 6 | 7 | Usage 8 | ------------------------- 9 | 10 | - hosts: servers 11 | roles: 12 | - unbound 13 | 14 | 15 | License 16 | ------------------------- 17 | 18 | GPLv3 19 | -------------------------------------------------------------------------------- /roles/unbound/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dns_root_hints: http://www.internic.net/domain/named.cache 3 | -------------------------------------------------------------------------------- /roles/unbound/files/firewall.sh: -------------------------------------------------------------------------------- 1 | ipt -A INPUT -p udp --dport 53 -j ACCEPT 2 | ipt -A INPUT -p tcp --dport 53 -j ACCEPT 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound-ip-up.d: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | PATH=/sbin:/usr/sbin:/bin:/usr/bin 4 | 5 | if ! pgrep unbound >/dev/null 2>&1; then 6 | service unbound restart 7 | fi 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/caching-timeouts.conf: -------------------------------------------------------------------------------- 1 | server: 2 | cache-min-ttl: 3600 3 | cache-max-ttl: 86400 4 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/caching-tweaking.conf: -------------------------------------------------------------------------------- 1 | server: 2 | # the number of slabs to use for cache and must be a power of 2 times the 3 | # number of num-threads set above. more slabs reduce lock contention, but 4 | # fragment memory usage. 5 | msg-cache-slabs: 8 6 | rrset-cache-slabs: 8 7 | infra-cache-slabs: 8 8 | key-cache-slabs: 8 9 | 10 | # Increase the memory size of the cache. Use roughly twice as much rrset cache 11 | # memory as you use msg cache memory. Due to malloc overhead, the total memory 12 | # usage is likely to rise to double (or 2.5x) the total cache memory. The test 13 | # box has 4gig of ram so 256meg for rrset allows a lot of room for cacheed objects. 14 | rrset-cache-size: 256m 15 | msg-cache-size: 128m 16 | 17 | # buffer size for UDP port 53 incoming (SO_RCVBUF socket option). This sets 18 | # the kernel buffer larger so that no messages are lost in spikes in the traffic. 19 | so-rcvbuf: 1m 20 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/disable-dnssec.conf: -------------------------------------------------------------------------------- 1 | server: 2 | module-config: "iterator" 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/edns-buffer-size.conf: -------------------------------------------------------------------------------- 1 | server: 2 | edns-buffer-size: 1280 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/harden-glue.conf: -------------------------------------------------------------------------------- 1 | server: 2 | harden-glue: yes 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/hide-version.conf: -------------------------------------------------------------------------------- 1 | server: 2 | hide-version: yes 3 | hide-identity: yes 4 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/jostle-timeout.conf: -------------------------------------------------------------------------------- 1 | server: 2 | jostle-timeout: 500 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/minimal-responses.conf: -------------------------------------------------------------------------------- 1 | server: 2 | minimal-responses: yes 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/no-logging.conf: -------------------------------------------------------------------------------- 1 | server: 2 | verbosity: 0 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/number-of-threads.conf: -------------------------------------------------------------------------------- 1 | server: 2 | num-threads: 4 3 | -------------------------------------------------------------------------------- /roles/unbound/files/unbound.conf.d/root-hints.conf: -------------------------------------------------------------------------------- 1 | server: 2 | root-hints: "/var/lib/unbound/root.hints" 3 | -------------------------------------------------------------------------------- /roles/unbound/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart unbound 3 | service: 4 | name: unbound 5 | state: restarted 6 | enabled: yes 7 | -------------------------------------------------------------------------------- /roles/unbound/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - firewall 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - wheezy 9 | - jessie 10 | -------------------------------------------------------------------------------- /roles/unbound/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install unbound 3 | apt: 4 | name: unbound 5 | 6 | - name: Copy Configuration 7 | copy: 8 | src: "unbound.conf.d/" 9 | dest: "/etc/unbound/unbound.conf.d/" 10 | mode: 0644 11 | owner: root 12 | group: root 13 | notify: restart unbound 14 | 15 | - name: Fix unbound default config 16 | replace: 17 | dest: /etc/unbound/unbound.conf.d/qname-minimisation.conf 18 | regexp: "qname-minimisation: yes" 19 | replace: "qname-minimisation: no" 20 | when: (ansible_distribution == "Debian" and (ansible_distribution_version is version_compare("11", "<"))) 21 | 22 | - name: Disable qname minimisation 23 | copy: 24 | content: "server:\n qname-minimisation: no\n" 25 | dest: /etc/unbound/unbound.conf.d/qname-minimisation.conf 26 | owner: root 27 | group: root 28 | mode: '0644' 29 | when: (ansible_distribution == "Debian" and (ansible_distribution_version is version_compare("11", ">="))) 30 | 31 | - name: Copy network hook 32 | copy: 33 | src: unbound-ip-up.d 34 | dest: /etc/network/if-up.d/unbound 35 | mode: 0755 36 | owner: root 37 | group: root 38 | 39 | - name: Generate Configuration 40 | template: 41 | src: "{{ item }}" 42 | dest: "/etc/unbound/unbound.conf.d/{{ item }}" 43 | mode: 0644 44 | owner: root 45 | group: root 46 | with_items: 47 | - access-control.conf 48 | - listen-on-all-interfaces.conf 49 | - remote-control.conf 50 | notify: restart unbound 51 | 52 | - name: Get root.hints 53 | get_url: 54 | url: '{{ dns_root_hints }}' 55 | dest: '/var/lib/unbound/root.hints' 56 | notify: restart unbound 57 | 58 | - name: Open firewall for DNS 59 | copy: 60 | src: firewall.sh 61 | dest: "{{ firewall_path }}/30-unbound" 62 | mode: 0644 63 | owner: root 64 | group: root 65 | when: firewall_enabled 66 | notify: reload firewall 67 | -------------------------------------------------------------------------------- /roles/unbound/templates/access-control.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | server: 3 | access-control: 127.0.0.1 allow 4 | access-control: 10.196.0.0/16 allow 5 | access-control: fd2f:5119:f2c::/48 allow 6 | access-control: 2a06:8782::/32 allow 7 | -------------------------------------------------------------------------------- /roles/unbound/templates/listen-on-all-interfaces.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | server: 3 | interface: 127.0.0.1 4 | interface: {{ batman_ipv4.address}} 5 | {% if batman_ipv6_global and batman_ipv6_global.address != batman_ipv6_local.address %} 6 | interface: {{ batman_ipv6_global.address }} 7 | {% endif %} 8 | interface: {{ batman_ipv6_local.address }} 9 | do-ip4: yes 10 | do-ip6: yes 11 | do-udp: yes 12 | do-tcp: yes 13 | ip-freebind: yes 14 | -------------------------------------------------------------------------------- /roles/unbound/templates/remote-control.conf: -------------------------------------------------------------------------------- 1 | remote-control: 2 | control-enable: yes 3 | {% if (ansible_distribution == "Debian" and (ansible_distribution_version is version_compare("11", "<"))) %} 4 | control-interface: /run/unbound.sock 5 | {% else %} 6 | control-interface: 127.0.0.1 7 | control-port: 8953 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /roles/website/README.md: -------------------------------------------------------------------------------- 1 | website 2 | ========================= 3 | 4 | Install Jeykll as used for the main website of Freifunk Bremen. 5 | 6 | 7 | Configuration 8 | ------------------------- 9 | 10 | See `defaults/main.yml` for available parameters. 11 | 12 | Note that the `website_webhook_secret` parameter doesn't have a default value 13 | Since its value must remain secret, the value must be specified on command line when running ansible-playbook (with `-e "website_webhook_secret=thesecret"`) 14 | 15 | 16 | Configuration of Github webhook 17 | -------------------------------- 18 | 19 | Go to the Webhook page at https://github.com/FreifunkBremen/bremen.freifunk.net/settings/hooks/ (you need admin permissions for this), and add a new webhook with these settings: 20 | * payload url: http://bremen.freifunk.net/webhook.php 21 | * content type: application/json 22 | * secret: the value that was passed on command line for `website_webhook_secret` parameter 23 | * for events: "Just the push event." 24 | 25 | The webhook will only work if it originates from the FreifunkBremen/bremen.freifunk.net repository and is for the master branch. 26 | 27 | 28 | Usage 29 | ------------------------- 30 | 31 | - hosts: servers 32 | roles: 33 | - website 34 | 35 | 36 | License 37 | ------------------------- 38 | 39 | GPLv3 40 | -------------------------------------------------------------------------------- /roles/website/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | website_email: 'info@bremen.freifunk.net' 3 | website_user: 'website' 4 | website_group: 'website' 5 | website_domain: '{{ main_domain }}' 6 | #website_webhook_secret: '' # must be provided on command line 7 | website_git_root: 'https://github.com/FreifunkBremen/bremen.freifunk.net' 8 | website_git_commit: 'd8f757d21294234aa2b8c8cb2340719f0d3ace0d' 9 | -------------------------------------------------------------------------------- /roles/website/files/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataPath": "https://downloads.bremen.freifunk.net/data/", 3 | "siteName": "Freifunk Bremen", 4 | "mapSigmaScale": 0.25, 5 | "showContact": false, 6 | "maxAge": 3, 7 | "globalInfos": [ 8 | { 9 | "name": "Wochenstatistik", 10 | "href": "https://downloads.bremen.freifunk.net/data/nodes/globalGraph.png", 11 | "thumbnail": "https://downloads.bremen.freifunk.net/data/nodes/globalGraph.png", 12 | "caption": "Entwicklung der Anzahl der Knoten und der Clients innerhalb der letzten 7 Tage" 13 | } 14 | ], 15 | "mapLayers": [ 16 | { 17 | "name": "Freifunk Bremen", 18 | "url": "//tiles.bremen.freifunk.net/{z}/{x}/{y}.png", 19 | "config": { 20 | "type": "osm", 21 | "attribution": "Design © Mapbox, CC-BY 3.0 — Daten © OpenStreetMap", 22 | "maxZoom": 20 23 | } 24 | }, 25 | { "name": "OpenStreetMap.Mapnik" }, 26 | { "name": "Stamen.TonerLite" } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /roles/website/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install jekyll dependencies 3 | bundler: 4 | gem_path: .bundle 5 | chdir: "/home/{{ website_user }}/.var/jekyll-envs/{{ website_domain }}" 6 | become: yes 7 | become_user: "{{ website_user }}" 8 | 9 | - name: run jekyll 10 | command: "/home/{{ website_user }}/.local/bin/update-jekyll.sh" 11 | become: yes 12 | become_user: "{{ website_user }}" 13 | -------------------------------------------------------------------------------- /roles/website/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - apt 4 | - sudo 5 | - tools 6 | - apache 7 | - letsencrypt 8 | - php 9 | - ruby 10 | - git 11 | - nodejs 12 | galaxy_info: 13 | platforms: 14 | - name: Debian 15 | versions: 16 | - jessie 17 | -------------------------------------------------------------------------------- /roles/website/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ main_domain }} 5 | ServerAlias {{ alt_domain }} www.{{ main_domain }} www.{{ alt_domain }} 6 | 7 | # set this to customers mail address 8 | ServerAdmin {{ website_email }} 9 | 10 | SuexecUserGroup {{ website_user }} {{ website_group }} 11 | 12 | DocumentRoot /var/www/{{ website_user }}/domains/{{ website_domain }} 13 | 14 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 15 | Options +SymLinksIfOwnerMatch -Includes 16 | 17 | 18 | Alias /icons /usr/share/apache2/icons 19 | ScriptAlias /cgi-bin /var/www/{{ website_user }}/cgi-bin 20 | ScriptAlias /fcgi-bin /var/www/{{ website_user }}/fcgi-bin 21 | Include /etc/apache2/user-php-exec.conf 22 | 23 | ErrorLog /var/log/apache2/website/default-error.log 24 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 25 | 26 | SSLEngine on 27 | SSLCertificateFile /etc/letsencrypt/certs/{{ website_domain }}/fullchain.pem 28 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ website_domain }}/privkey.pem 29 | 30 | -------------------------------------------------------------------------------- /roles/website/templates/php-fcgi-starter: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # Set safe path 4 | export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 5 | 6 | # Set user environment 7 | export USER={{ website_user }} 8 | export HOME=/home/{{ website_user }} 9 | 10 | PHP_FCGI_CHILDREN=0 11 | export PHP_FCGI_CHILDREN 12 | PHP_FCGI_MAX_REQUESTS=250 13 | export PHP_FCGI_MAX_REQUESTS 14 | exec php-cgi 15 | -------------------------------------------------------------------------------- /roles/website/templates/update-jekyll.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env sh 2 | 3 | # shellcheck disable=SC1091 4 | . /etc/profile 5 | 6 | set -eu 7 | 8 | SOURCE="$HOME/.var/jekyll-envs/{{ website_domain }}/" 9 | DESTINATION="/var/www/{{ website_user }}/domains/{{ website_domain }}/" 10 | 11 | cd "$SOURCE" 12 | 13 | git fetch --quiet origin 14 | git reset --quiet --hard origin/master 15 | git submodule --quiet update --init 16 | 17 | bundle config set --local path .bundle 18 | bundle install --quiet 19 | 20 | exec bundle exec jekyll build --quiet --destination "$DESTINATION" 21 | -------------------------------------------------------------------------------- /roles/wiki/README.md: -------------------------------------------------------------------------------- 1 | wiki 2 | ========================= 3 | 4 | Install gollum 5 | used by Freifunk Bremen 6 | as wiki system 7 | 8 | 9 | Usage 10 | ------------------------- 11 | 12 | - hosts: servers 13 | roles: 14 | - wiki 15 | 16 | 17 | Github SSH Deploy Key 18 | ------------------------- 19 | During installation an SSH key will be created for the wiki user. 20 | The key will be created at /home/wiki/.ssh/id_rsa.pub . 21 | It must be added at https://github.com/FreifunkBremen/wiki/settings/keys 22 | as new key (with write access), so that wiki changes can be pushed to Github. 23 | 24 | 25 | Gollum Logs 26 | ------------------------- 27 | Gollum log files are stored in /home/wiki/.config/service/gollum/log/main/. 28 | The "current" file contains the most recent log lines. 29 | To display human-readable timestamps, filter the log file through "tai64nlocal", eg. like this: 30 | 31 | tai64nlocal < current | less 32 | 33 | 34 | License 35 | ------------------------- 36 | 37 | GPLv3 38 | -------------------------------------------------------------------------------- /roles/wiki/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | wiki_gollum_git_root: 'https://github.com/FreifunkBremen/gollum.git' 3 | wiki_gollum_git_commit: '428b397389961b7f0069528b600816d5050cc364' 4 | wiki_content_git_root: 'https://github.com/FreifunkBremen/wiki.git' 5 | wiki_email: 'info@bremen.freifunk.net' 6 | wiki_user: 'wiki' 7 | wiki_group: 'wiki' 8 | wiki_subdomain: 'wiki' 9 | wiki_domain: '{{ wiki_subdomain }}.{{ main_domain }}' 10 | wiki_gollum_port: '63112' 11 | wiki_http_username: 'wellenfunk' 12 | wiki_http_password: 'foobar' 13 | -------------------------------------------------------------------------------- /roles/wiki/files/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/roles/wiki/files/favicon.ico -------------------------------------------------------------------------------- /roles/wiki/files/gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Anonymous 3 | email = anon@anon.com 4 | -------------------------------------------------------------------------------- /roles/wiki/files/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /Treffen/ 3 | Disallow: /Entwuerfe/ 4 | Disallow: /edit/ 5 | Disallow: /history/ 6 | Disallow: /fileview 7 | Disallow: /latest_changes 8 | -------------------------------------------------------------------------------- /roles/wiki/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - apache 4 | - apt 5 | - git 6 | - letsencrypt 7 | - ruby 8 | - sudo 9 | - tools 10 | galaxy_info: 11 | platforms: 12 | - name: Debian 13 | versions: 14 | - jessie 15 | -------------------------------------------------------------------------------- /roles/wiki/templates/apache2.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | 4 | ServerName {{ wiki_subdomain }}.{{ main_domain }} 5 | ServerAlias {{ wiki_subdomain }}.{{ alt_domain }} 6 | 7 | # Don't add header to proxy 8 | ProxyAddHeaders Off 9 | 10 | # set this to customers mail address 11 | ServerAdmin {{ wiki_email }} 12 | 13 | DocumentRoot /var/www/{{ wiki_user }}/domains/{{ wiki_subdomain }}.{{ main_domain }} 14 | 15 | AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Indexes,MultiViews,SymLinksIfOwnerMatch 16 | Options +SymLinksIfOwnerMatch -Includes 17 | 18 | 19 | SuexecUserGroup {{ wiki_user }} {{ wiki_group }} 20 | 21 | ErrorLog /var/log/apache2/{{ wiki_user }}/default-error.log 22 | ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ ANONYMIZED] %M% ,\ referer\ %{Referer}i" 23 | 24 | SSLEngine on 25 | SSLCertificateFile /etc/letsencrypt/certs/{{ wiki_domain }}/fullchain.pem 26 | SSLCertificateKeyFile /etc/letsencrypt/certs/{{ wiki_domain }}/privkey.pem 27 | 28 | -------------------------------------------------------------------------------- /roles/wiki/templates/gollum.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Gollum git based wiki 3 | 4 | [Service] 5 | WorkingDirectory=%h/.opt/gollum 6 | SyslogIdentifier=%p 7 | ExecStart=/usr/bin/bundle exec bin/gollum --port {{ wiki_gollum_port }} --host 127.0.0.1 --adapter rugged --css --h1-title --ref wiki "%h/.var/gollum-envs/ff-bremen" 8 | Restart=always 9 | RestartSec=5 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /roles/wiki/templates/htaccess: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | DirectoryIndex disabled 4 | RewriteEngine On 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteRule ^(.*)$ http://127.0.0.1:{{ wiki_gollum_port }}/$1 [P,L] 7 | RequestHeader set X-Forwarded-Proto "https" env=HTTPS 8 | 9 | SetEnvIfNoCase Request_URI ^/gollum/(create|edit|livepreview|delete|rename)/ require_auth=true 10 | 11 | AuthType basic 12 | AuthName "Dies ist ein Spamschutz. Benutzername: wellenfunk, Passwort: foobar" 13 | AuthUserFile /var/www/{{ wiki_user }}/domains/{{ wiki_domain }}/.htpasswd 14 | ErrorDocument 401 "Die Benutzerabfrage dient lediglich der Spamvermeidung. Die Benutzerdaten lauten: Benutzername: wellenfunk, Passwort: foobar" 15 | 16 | Order Deny,Allow 17 | Deny from All 18 | Satisfy any 19 | Allow from env=!require_auth 20 | Require valid-user 21 | -------------------------------------------------------------------------------- /roles/yanic/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | yanic_publisher: false 3 | yanic_respondd: true 4 | yanic_respondd_collect_interval: "1m" 5 | yanic_respondd_interface: "eth0" 6 | 7 | yanic_webserver: false 8 | yanic_webserver_bind: "127.0.0.1:8080" 9 | yanic_webserver_webroot: "/var/www/html/meshviewer" 10 | 11 | yanic_nodes: true 12 | yanic_nodes_state_path: "/var/lib/yanic.json" 13 | yanic_nodes_save_interval: "5s" 14 | yanic_nodes_offline_after: "10m" 15 | yanic_nodes_prune_after: "7d" 16 | 17 | yanic_meshviewer_version: 2 18 | yanic_meshviewer_path: "/var/www/html/meshviewer/data" 19 | yanic_meshviewer_nodes: "{{yanic_meshviewer_path}}/nodes.json" 20 | yanic_meshviewer_graph: "{{yanic_meshviewer_path}}/graph.json" 21 | 22 | yanic_database_delete_after: "7d" 23 | yanic_database_delete_interval: "1h" 24 | 25 | yanic_socket: 26 | - enable: false 27 | type: unix 28 | address: "/var/lib/yanic/database.socket" 29 | yanic_influxdb: 30 | - enable: false 31 | host: http://localhost:8086 32 | database: ffhb 33 | username: "" 34 | password: "" 35 | -------------------------------------------------------------------------------- /roles/yanic/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart yanic 3 | service: 4 | name: yanic 5 | state: restarted 6 | 7 | - name: restart yanic-publish 8 | service: 9 | name: yanic-publish.timer 10 | state: restarted 11 | 12 | - name: reload systemd 13 | systemd: 14 | daemon_reload: yes 15 | -------------------------------------------------------------------------------- /roles/yanic/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - go 4 | galaxy_info: 5 | platforms: 6 | - name: Debian 7 | versions: 8 | - jessie 9 | -------------------------------------------------------------------------------- /roles/yanic/templates/config.toml: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [respondd] 3 | enable = {{ yanic_respondd | ternary('true','false') }} 4 | collect_interval = "{{ yanic_respondd_collect_interval }}" 5 | interface = "{{ yanic_respondd_interface }}" 6 | 7 | [webserver] 8 | enable = {{ yanic_webserver | ternary('true','false') }} 9 | bind = "{{ yanic_webserver_bind }}" 10 | webroot = "{{ yanic_webserver_webroot }}" 11 | 12 | [nodes] 13 | enable = {{yanic_nodes | ternary('true','false') }} 14 | state_path = "{{yanic_nodes_state_path}}" 15 | save_interval = "{{yanic_nodes_save_interval}}" 16 | offline_after = "{{yanic_nodes_offline_after}}" 17 | prune_after = "{{yanic_nodes_prune_after}}" 18 | 19 | 20 | [meshviewer] 21 | version = {{yanic_meshviewer_version}} 22 | nodes_path = "{{yanic_meshviewer_nodes}}" 23 | graph_path = "{{yanic_meshviewer_graph}}" 24 | 25 | [database] 26 | delete_after = "{{ yanic_database_delete_after }}" 27 | delete_interval = "{{ yanic_database_delete_interval }}" 28 | 29 | {% for db in yanic_influxdb %} 30 | [[database.connection.influxdb]] 31 | enable = {{ db.enable | ternary('true','false') }} 32 | address = "{{ db.host }}" 33 | database = "{{ db.database }}" 34 | username = "{{ db.username }}" 35 | password = "{{ db.password }}" 36 | {% endfor %} 37 | 38 | {% for db in yanic_socket %} 39 | [[database.connection.socket]] 40 | enable = {{ db.enable | ternary('true','false') }} 41 | type = "{{ db.type }}" 42 | address = "{{ db.address }}" 43 | {% endfor %} 44 | -------------------------------------------------------------------------------- /roles/yanic/templates/yanic-publish-ssh-master.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Persistent SSH connection to webserver 3 | After=network-online.target 4 | 5 | [Service] 6 | ExecStart=/usr/bin/ssh -M -N ${REMOTE_HOST} 7 | EnvironmentFile=/etc/default/yanic-publish 8 | User=respond-collector 9 | Restart=always 10 | RestartSec=10 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /roles/yanic/templates/yanic-publish.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Publish data of yanic on downloads server 3 | 4 | [Service] 5 | ExecStart=/usr/bin/rsync --del -rt {{ yanic_nodes_path }}/ ${REMOTE_HOST}:${REMOTE_PATH} 6 | EnvironmentFile=/etc/default/yanic-publish 7 | User=yanic 8 | Type=oneshot 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /roles/yanic/templates/yanic-publish.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Publish data of yanic on downloads server every minute 3 | 4 | [Timer] 5 | OnBootSec=15min 6 | OnUnitActiveSec=1min 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /roles/yanic/templates/yanic.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=yanic 3 | 4 | [Service] 5 | Type=simple 6 | User=yanic 7 | ExecStart=/opt/go/bin/yanic -config /etc/yanic.conf 8 | Restart=always 9 | RestartSec=5s 10 | Environment=PATH=/usr/bin:/usr/local/bin 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /scripts/open.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" 3 | gpg --batch --use-agent --decrypt "${SCRIPT_DIR}/../vault_passphrase.gpg" 4 | -------------------------------------------------------------------------------- /scripts/resign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" 3 | 4 | ## key of: 5 | # genofire: 386ED1BF848ABB4A6B4A3C45FC83907C125BC2BC 6 | # janeric: BCD82B6C729A931C8CB382E5864F5B9B0642DF6F 7 | # jplitza: D7E72BFC9E133E0452DAFBCBB17F2106D8CCEC27 8 | # mortzu: 62D00A6960AC2256A24240BCD568B1E5EB1A6E50 9 | # ollibaba: D9E17720908282C3A8232361DB7D9F68F00F513E 10 | 11 | 12 | "${SCRIPT_DIR}/open.sh" | gpg -e \ 13 | -r 386ED1BF848ABB4A6B4A3C45FC83907C125BC2BC \ 14 | -r BCD82B6C729A931C8CB382E5864F5B9B0642DF6F \ 15 | -r D7E72BFC9E133E0452DAFBCBB17F2106D8CCEC27 \ 16 | -r 62D00A6960AC2256A24240BCD568B1E5EB1A6E50 \ 17 | -r D9E17720908282C3A8232361DB7D9F68F00F513E \ 18 | -o "${SCRIPT_DIR}/../vault_passphrase.gpg" 19 | -------------------------------------------------------------------------------- /vagrant/.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "debian/jessie64" 16 | 17 | # Create a private network, which allows host-only access to the machine 18 | # using a specific IP. 19 | config.vm.network "private_network", ip: "192.168.33.10" 20 | 21 | # Create a public network, which generally matched to bridged network. 22 | # Bridged networks make the machine appear as another physical device on 23 | # your network. 24 | # config.vm.network "public_network" 25 | 26 | # Share an additional folder to the guest VM. The first argument is 27 | # the path on the host to the actual folder. The second argument is 28 | # the path on the guest to mount the folder. And the optional third 29 | # argument is a set of non-required options. 30 | # config.vm.synced_folder "../data", "/vagrant_data" 31 | 32 | # Install authorized keys 33 | authorized_keys = Dir.glob(ENV["HOME"] + "/.ssh/*.pub").map{|file| File.read(file) }.join 34 | config.vm.provision "shell", inline: <<-SHELL 35 | mkdir -p /root/.ssh 36 | echo "#{authorized_keys}" >> /root/.ssh/authorized_keys 37 | SHELL 38 | end 39 | -------------------------------------------------------------------------------- /vault_passphrase.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreifunkBremen/ansible/37228a3d1c1cbab8d633b85266f6029a356bb3b7/vault_passphrase.gpg --------------------------------------------------------------------------------