├── .editorconfig ├── .gitignore ├── .gitmodules ├── .travis.yml ├── LICENSE.md ├── Makefile ├── README.md ├── ansible ├── ansible.cfg ├── files │ └── apt │ │ ├── tor.asc │ │ └── weechat.asc ├── group_vars │ └── all │ │ ├── donate.yml │ │ ├── dotfiles.yml │ │ ├── ldap.yml │ │ ├── mail.yml │ │ └── system.yml ├── main.yml └── tasks │ ├── cron │ └── main.yml │ ├── dns │ └── main.yml │ ├── docker │ ├── main.post.yml │ └── main.pre.yml │ ├── hashbang │ ├── main.yml │ └── templates │ │ ├── etc │ │ ├── hashbang │ │ │ ├── welcome.j2 │ │ │ ├── welcome.notmux.j2 │ │ │ ├── welcome.post.j2 │ │ │ ├── welcome.pre.j2 │ │ │ └── welcome.tmux.j2 │ │ └── skel │ │ │ └── Mail │ │ │ └── new │ │ │ └── msg.welcome.j2 │ │ └── usr │ │ └── local │ │ └── share │ │ └── man │ │ └── man7 │ │ └── hashbang.7.j2 │ ├── logging │ └── main.yml │ ├── mail │ └── main.yml │ ├── misc │ └── main.yml │ ├── nginx │ └── main.yml │ ├── packages │ └── main.yml │ ├── profile │ └── main.yml │ ├── prometheus │ └── main.yml │ ├── security │ └── main.yml │ ├── tor │ └── main.yml │ └── userdb │ ├── main.yml │ └── templates │ └── usr │ └── local │ └── bin │ └── authorized-keys.j2 ├── config.sample.json └── packer ├── build.json ├── http └── preseed.cfg └── publish.json /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.sh] 2 | indent_style = space 3 | indent_size = 4 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | dist 3 | config.json 4 | *.retry 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashbang/shell-server/3925adb7ca54058c04ba16d1fcdfb9b17fef2e49/.gitmodules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | services: 3 | - docker 4 | 5 | cache: 6 | pip: {} 7 | 8 | addons: 9 | apt: 10 | packages: 11 | - wget 12 | - unzip 13 | - python-pip 14 | 15 | env: 16 | global: 17 | - REPO=hashbang/shell-server 18 | 19 | before_install: 20 | - test -f /usr/local/bin/packer || (wget -O packer.zip https://releases.hashicorp.com/packer/1.2.4/packer_1.2.4_linux_amd64.zip && unzip -o packer.zip && sudo mv packer /usr/local/bin/) 21 | - sudo -H pip install 'ansible>=2.5' 22 | 23 | script: 24 | - make docker 25 | 26 | # after_success: 27 | # - if [ "$TRAVIS_BRANCH" == "master" ]; then docker login -u $DOCKER_USER -p $DOCKER_PASS && docker tag shell-server $REPO:latest && docker push $REPO; fi 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Hashbang Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | PACKER=packer 3 | export CHECKPOINT_DISABLE := 1 4 | export PACKER_CACHE_DIR := \ 5 | $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/.packer/cache 6 | export VERSION := $(shell date -u +%Y%m%d%H%M) 7 | EXECUTABLES = $(PACKER) ansible 8 | K := $(foreach exec,$(EXECUTABLES),\ 9 | $(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH"))) 10 | WHICH-%: ; @which $* > /dev/null 11 | 12 | all: clean WHICH-qemu-system-x86_64 13 | $(PACKER) build --parallel=false packer/build.json 14 | 15 | clean: 16 | mkdir -p dist 17 | rm -rf dist/* 18 | rm -rf .packer/build 19 | 20 | docker: 21 | mkdir -p dist 22 | rm -rf dist/*docker* 23 | rm -rf .packer/build/docker 24 | $(PACKER) build -only docker packer/build.json 25 | 26 | qemu: WHICH-qemu-system-x86_64 27 | mkdir -p dist 28 | rm -rf dist/*qemu* 29 | rm -rf .packer/build/qemu 30 | $(PACKER) build -only qemu packer/build.json 31 | 32 | vagrant: 33 | mkdir -p dist 34 | rm -rf dist/*vagrant* 35 | rm -rf dist/*virtualbox* 36 | rm -rf .packer/build/virtualbox 37 | $(PACKER) build -only virtualbox packer/build.json 38 | 39 | lxc: 40 | mkdir -p dist 41 | rm -rf dist/*lxc* 42 | rm -rf .packer/build/lxc 43 | $(PACKER) build -only lxc packer/build.json 44 | 45 | release: 46 | bash scripts/release.sh 47 | 48 | .PHONY: all docker qemu vagrant lxc clean 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # #! Shell Server # 2 | 3 | 4 | 5 | ## About ## 6 | 7 | This is the central build and management repository for #! shell servers. 8 | 9 | It should contain everything required to run your own #! shell server, or to 10 | develop changes to be deployed to all existing deployed servers. 11 | 12 | Existing servers automatically update from this repo via ansible-pull. 13 | 14 | ## Requirements ## 15 | 16 | | Tool | Version | Needed for Builder | 17 | | ---------- | ------- | -------------------- | 18 | | Ansible | v2.5+ | all | 19 | | Packer | v1.3x+ | all | 20 | | Docker | v18.0+ | Docker | 21 | | qemu | v2.12+ | qemu, libvirt | 22 | | Virtualbox | v5.2+ | virtualbox, vagrant | 23 | | Vagrant | v2.1.1+ | vagrant | 24 | | Linux | v4.16+ | lxc, libvirt | 25 | | lxc | v3.0+ | lxc | 26 | 27 | ## Building ## 28 | 29 | You will normally need a #! account to use these, as they authenticate users 30 | against our NSS services by default. 31 | 32 | ### Docker ### 33 | 34 | #### Build image #### 35 | ```sh 36 | make docker 37 | ``` 38 | 39 | #### Import image #### 40 | ```sh 41 | docker import .packer/build/docker/docker.tar hashbang/shell-server:local-latest 42 | ``` 43 | 44 | #### Start container #### 45 | ```sh 46 | docker run \ 47 | -it \ 48 | --rm \ 49 | --name shell-server \ 50 | -p 8080:80 \ 51 | -p 4443:443 \ 52 | -p 2222:22 \ 53 | -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 54 | --stop-signal SIGRTMIN+3 \ 55 | --cap-add SYS_ADMIN \ 56 | --cap-add SYS_RESOURCE \ 57 | --security-opt apparmor=unconfined \ 58 | --security-opt seccomp=unconfined \ 59 | hashbang/shell-server:local-latest \ 60 | /lib/systemd/systemd 61 | ``` 62 | 63 | #### User shell #### 64 | ```sh 65 | ssh -p2222 your-hashbang-user@localhost 66 | ``` 67 | 68 | #### Root shell #### 69 | ```sh 70 | docker exec -it shell-server bash 71 | ``` 72 | 73 | ### LXC ### 74 | 75 | #### Build image #### 76 | ```sh 77 | make lxc 78 | ``` 79 | 80 | #### User shell #### 81 | ``` 82 | TODO 83 | ``` 84 | 85 | #### Root shell #### 86 | ``` 87 | TODO 88 | ``` 89 | 90 | ### Vagrant ### 91 | 92 | #### Build Image #### 93 | ```sh 94 | make vagrant 95 | ``` 96 | 97 | #### Start server #### 98 | ```sh 99 | vagrant init hashbang/shell-server 100 | vagrant up 101 | ``` 102 | 103 | #### User shell #### 104 | ```sh 105 | ssh -p2222 your-hashbang-user@localhost 106 | ``` 107 | 108 | #### Root shell #### 109 | ```sh 110 | vagrant ssh 111 | ``` 112 | 113 | ### Libvirt ### 114 | 115 | #### Build Image #### 116 | ```sh 117 | make qemu 118 | ``` 119 | 120 | #### Start server #### 121 | 122 | ```sh 123 | virt-install \ 124 | --name shell-server \ 125 | --os-type linux \ 126 | --os-variant debian9 \ 127 | --ram 512 \ 128 | --vcpus 2 \ 129 | --disk path=.packer/build/qemu/packer-qemu \ # no file extension 130 | --network user \ 131 | --noautoconsole \ 132 | --import \ 133 | --force 134 | ``` 135 | 136 | #### User shell #### 137 | ```sh 138 | virsh --connect qemu+ssh://username@shell-server/system 139 | ``` 140 | 141 | #### Root shell #### 142 | ``` 143 | TODO 144 | ``` 145 | 146 | ### Qemu ### 147 | 148 | #### Build Image #### 149 | ```sh 150 | make qemu 151 | ``` 152 | 153 | #### Start server #### 154 | 155 | ``` 156 | qemu-system-x86_64 \ 157 | -m 512M \ 158 | -machine type=pc,accel=kvm \ 159 | -net nic -net user,hostfwd=tcp::2222-:22 \ 160 | -drive format=qcow2,file=.packer/build/qemu/packer-qemu # no file extension 161 | ``` 162 | 163 | #### User shell #### 164 | 165 | ``` 166 | TODO 167 | ``` 168 | 169 | #### Root shell #### 170 | 171 | ``` 172 | TODO 173 | ``` 174 | 175 | ## Development ## 176 | 177 | Once you have root access on a development debian server be it local or remote, 178 | you can test your locally made ansible playbook changes as follows. 179 | 180 | ### Run Ansible Playbook 181 | ```sh 182 | ansible-playbook \ 183 | -u root \ 184 | -i "localhost," \ 185 | -e ansible_ssh_port=2222 \ 186 | ansible/main.yml 187 | ``` 188 | 189 | ## Deployment ## 190 | 191 | ### Kubernetes ### 192 | TODO 193 | 194 | ### Amazon ### 195 | TODO 196 | 197 | ### DigitalOcean ### 198 | TODO 199 | 200 | ### Google Cloud ### 201 | TODO 202 | 203 | ### Azure ### 204 | TODO 205 | 206 | ### Bare Metal ### 207 | ```sh 208 | ansible-playbook -u root -i "target-server.com," ansible/main.yml 209 | ``` 210 | 211 | ## Releasing ## 212 | 213 | 1. Copy config sample and populate with your credentials as desired: 214 | 215 | ```sh 216 | cp config.sample.json config.json 217 | vim config.json 218 | ``` 219 | 220 | 2. Build, sign, and publish all image types 221 | ```sh 222 | make build release 223 | ``` 224 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ./hosts 3 | roles_path = ./roles 4 | host_key_checking = False 5 | retry_files_enabled = False 6 | -------------------------------------------------------------------------------- /ansible/files/apt/tor.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 35 | =Kjcs 36 | -----END PGP PUBLIC KEY BLOCK----- 37 | -------------------------------------------------------------------------------- /ansible/files/apt/weechat.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 49 | qbO3wgTCCdnoticOvw== 50 | =xmBr 51 | -----END PGP PUBLIC KEY BLOCK----- 52 | -------------------------------------------------------------------------------- /ansible/group_vars/all/donate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | bitcoin: "1DtTvCLiUMhs21QcETQzLyiqxoopUjqBSU" 3 | google_wallet: "donate@hashbang.sh" 4 | paypal: "http://goo.gl/aSQWy0" 5 | -------------------------------------------------------------------------------- /ansible/group_vars/all/dotfiles.yml: -------------------------------------------------------------------------------- 1 | --- 2 | repository: "https://github.com/hashbang/dotfiles" 3 | stow: 4 | - bash 5 | - git 6 | - gnupg 7 | - hashbang 8 | - ssh 9 | - tmux 10 | - weechat 11 | - zsh 12 | -------------------------------------------------------------------------------- /ansible/group_vars/all/ldap.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dc_name: dc=hashbang,dc=sh 3 | -------------------------------------------------------------------------------- /ansible/group_vars/all/mail.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cert_fp: "73:E7:EC:E1:53:7F:D6:09:C9:3A:B3:62:84:64:7B:1D:D3:85:DF:D6" 3 | -------------------------------------------------------------------------------- /ansible/group_vars/all/system.yml: -------------------------------------------------------------------------------- 1 | --- 2 | domain: "hashbang.sh" 3 | # readonly credentials for primary userdb 4 | userdb_connectionstring: "postgresql://nss_pgsql:gei6Fucojei7Egei@userdb-attempt-too-do-user-989073-0.db.ondigitalocean.com:25060/userdb?sslmode=require" 5 | userdb_apidomain: "https://userdb.hashbang.sh" 6 | 7 | -------------------------------------------------------------------------------- /ansible/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: false 4 | pre_tasks: 5 | - name: Install python2 for Ansible 6 | raw: bash -c "test -e /usr/bin/python3 || (apt-get -qqy update && apt install -qqy python3-minimal)" 7 | register: output 8 | changed_when: output.stdout != "" 9 | - name: Gathering Facts 10 | setup: 11 | 12 | tasks: 13 | 14 | - name: Remove prometheus-node-exporter 15 | apt: 16 | name: 17 | - prometheus-node-exporter 18 | state: absent 19 | 20 | - name: Install minimum system packages 21 | apt: 22 | update_cache: true 23 | name: 24 | - ansible 25 | - git 26 | - gnupg 27 | - apt-transport-https 28 | - unattended-upgrades 29 | - systemd 30 | - apt-utils 31 | - lsb-release 32 | - curl 33 | - initscripts 34 | - systemd 35 | - udev 36 | - util-linux 37 | - openssh-server 38 | 39 | - name: Remove undesirable apt files 40 | file: 41 | path: /etc/apt/{{ item }} 42 | state: absent 43 | with_items: 44 | - trusted.gpg # Use trusted.gpg.d rather than a monolithic file! 45 | - # We aren't running Ubuntu ... 46 | sources.list.d/ppa_launchpad_net_ansible_ansible_ubuntu.list 47 | 48 | - name: Add the backports suite 49 | blockinfile: 50 | path: /etc/apt/sources.list 51 | create: yes 52 | content: | 53 | # Backports. Must be enabled per-package using a pin 54 | deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main contrib non-free 55 | deb-src http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main contrib non-free 56 | 57 | - name: Prefer the installed release over backports, by default 58 | copy: 59 | dest: /etc/apt/preferences 60 | mode: "0644" 61 | content: | 62 | # Give {{ ansible_distribution_release }} priority over everything 63 | Package: * 64 | Pin: release n={{ ansible_distribution_release }} 65 | Pin-Priority: 900 66 | 67 | # Give backports priority over other sources 68 | Package: * 69 | Pin: release n={{ ansible_distribution_release }}-backports 70 | Pin-Priority: 800 71 | 72 | - name: Pin Ansible from backports 73 | copy: 74 | dest: /etc/apt/preferences.d/ansible 75 | mode: "0644" 76 | content: | 77 | Package: ansible ieee-data python-netaddr 78 | Pin: release n={{ ansible_distribution_release }}-backports 79 | Pin-Priority: 990 80 | 81 | 82 | - name: Install latest ansible 83 | apt: 84 | name: ansible 85 | state: latest 86 | update_cache: yes 87 | 88 | - name: Determine if we are in a docker environment 89 | stat: path=/.dockerenv 90 | register: dockerenv 91 | 92 | - name: Run Docker preinit task 93 | include_tasks: tasks/docker/main.pre.yml 94 | when: dockerenv.stat.exists 95 | ignore_errors: True 96 | 97 | - name: Include tasks files 98 | include_tasks: "tasks/{{ task_name }}/main.yml" 99 | loop: 100 | - hashbang 101 | - logging 102 | - dns 103 | - mail 104 | - packages 105 | - profile 106 | - misc 107 | - userdb 108 | - security 109 | # temporarily disabled until prometheus user is fixed 110 | # - prometheus 111 | - nginx 112 | loop_control: 113 | loop_var: task_name 114 | 115 | - name: Run Docker postinit task 116 | include_tasks: tasks/docker/main.post.yml 117 | when: dockerenv.stat.exists 118 | ignore_errors: True 119 | -------------------------------------------------------------------------------- /ansible/tasks/cron/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Enable classic cron emulation with systemd timers 3 | block: 4 | - name: Install crontab target 5 | copy: 6 | dest: /etc/systemd/system/crontab.target 7 | content: | 8 | [Install] 9 | WantedBy=multi-user.target 10 | 11 | [Unit] 12 | Description=Simulates cron, limited to /etc/cron.* 13 | Requires=crontab@hourly.timer 14 | Requires=crontab@daily.timer 15 | Requires=crontab@weekly.timer 16 | Requires=crontab@monthly.timer 17 | 18 | - name: Install crontab service 19 | copy: 20 | dest: /etc/systemd/system/crontab@.service 21 | content: | 22 | [Unit] 23 | Description=%I job for /etc/cron.%I 24 | RefuseManualStart=yes 25 | RefuseManualStop=yes 26 | ConditionDirectoryNotEmpty=/etc/cron.%I 27 | 28 | [Service] 29 | Type=oneshot 30 | IgnoreSIGPIPE=no 31 | WorkingDirectory=/ 32 | ExecStart=/bin/run-parts --report /etc/cron.%I 33 | 34 | - name: Install crontab generic timer 35 | copy: 36 | dest: /etc/systemd/system/crontab@.timer 37 | content: | 38 | [Unit] 39 | Description=%I timer simulating /etc/cron.%I 40 | PartOf=crontab.target 41 | RefuseManualStart=yes 42 | RefuseManualStop=yes 43 | 44 | [Timer] 45 | OnCalendar=%I 46 | Persistent=yes 47 | 48 | - name: enable crontab service 49 | when: not dockerenv.stat.exists 50 | systemd: 51 | name: crontab 52 | enabled: yes 53 | masked: no 54 | -------------------------------------------------------------------------------- /ansible/tasks/dns/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install DNS packages 3 | apt: 4 | update_cache: yes 5 | name: 6 | - unbound 7 | - unbound-anchor 8 | - dns-root-data 9 | - dnsutils 10 | - ldnsutils 11 | - resolvconf 12 | 13 | - name: setup localhost as default nameserver 14 | lineinfile: 15 | path: /etc/resolvconf/resolv.conf.d/base 16 | create: true 17 | line: "nameserver 127.0.0.1" 18 | 19 | - name: setup hashbang.sh as default domain 20 | lineinfile: 21 | path: /etc/resolvconf/resolv.conf.d/tail 22 | create: true 23 | line: "domain hashbang.sh" 24 | 25 | - name: Setup unbound configuration 26 | block: 27 | - name: Use DNS root hints from the dns-root-data Debian package 28 | blockinfile: 29 | path: /etc/unbound/unbound.conf.d/debian.conf 30 | marker: "# {mark} ANSIBLE - DNS Root Hints" 31 | create: true 32 | block: | 33 | server: 34 | root-hints: "/usr/share/dns/root.hints" 35 | register: unbound_root_hints 36 | - name: Prefetch popular domains before the cache expires 37 | blockinfile: 38 | path: /etc/unbound/unbound.conf.d/prefetch.conf 39 | marker: "# {mark} ANSIBLE - Prefetch popular domains" 40 | create: true 41 | block: | 42 | server: 43 | prefetch: yes 44 | prefetch-key: yes 45 | register: unbound_prefetch 46 | - name: Enable RFC 7816 "DNS Query Name Minimisation to Improve Privacy" 47 | blockinfile: 48 | path: /etc/unbound/unbound.conf.d/qname-minimisation.conf 49 | marker: "# {mark} ANSIBLE - Enable RFC 7816" 50 | create: true 51 | block: | 52 | server: 53 | qname-minimisation: yes 54 | register: unbound_rfc_7816 55 | 56 | - name: unbound configuration hardening 57 | copy: 58 | dest: /etc/unbound/unbound.conf.d/harden.conf 59 | content: | 60 | server: 61 | # Do not expose information about the running deamon 62 | hide-identity: yes 63 | hide-version: yes 64 | 65 | # Harden against ridiculously-short buffer sizes (potential DoS vector) 66 | # This is against spec, but we aren't a public resolver. 67 | harden-short-bufsize: yes 68 | 69 | # Harden against abnormaly large queries (same reasoning) 70 | harden-large-queries: yes 71 | 72 | # Return NXDOMAIN for queries under a terminal known (and DNSSEC-validated) 73 | # to be NXDOMAIN. Improves caching and avoids certain attacks 74 | harden-below-nxdomain: yes 75 | 76 | # Use 0x20-encoded random nonces for authenticating queries. 77 | # Implementation of draft-dns-0x20, makes DNS poisoning harder 78 | use-caps-for-id: yes 79 | 80 | # Minimises queries sent upstream 81 | # Avoids information disclosure to root/TLD DNS servers & improves caching 82 | qname-minimisation: yes 83 | register: unbound_hardening 84 | 85 | - name: Enable & reload services 86 | when: | 87 | not dockerenv.stat.exists and ( 88 | unbound_hardening.changed or unbound_rfc_7816.changed or 89 | unbound_prefetch.changed or unbound_root_hints.changed) 90 | systemd: 91 | name: "{{ item }}" 92 | enabled: yes 93 | masked: no 94 | state: restarted 95 | 96 | with_items: 97 | - unbound 98 | 99 | - name: Enable & restart services 100 | when: | 101 | not dockerenv.stat.exists and ( 102 | unbound_hardening.changed or unbound_rfc_7816.changed or 103 | unbound_prefetch.changed or unbound_root_hints.changed) 104 | systemd: 105 | name: "{{ item }}" 106 | enabled: yes 107 | masked: no 108 | state: restarted 109 | 110 | with_items: 111 | - unbound-resolvconf 112 | - resolvconf 113 | -------------------------------------------------------------------------------- /ansible/tasks/docker/main.post.yml: -------------------------------------------------------------------------------- 1 | - name: Disable unbound systemd unit 2 | command: systemctl disable unbound 3 | -------------------------------------------------------------------------------- /ansible/tasks/docker/main.pre.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure resolvconf package does not link 3 | debconf: 4 | name: resolvconf 5 | question: resolvconf/linkify-resolvconf 6 | value: false 7 | vtype: boolean 8 | 9 | - name: Remove systemd units that don't make sense in a container 10 | file: 11 | state: absent 12 | path: "{{ item }}" 13 | with_items: 14 | - /lib/systemd/system/sysinit.target.wants/dev-hugepages.mount 15 | - /lib/systemd/system/sysinit.target.wants/dev-mqueue.mount 16 | - /lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service 17 | - /lib/systemd/system/sysinit.target.wants/proc-sys-fs-binfmt_misc.automount 18 | - /lib/systemd/system/sysinit.target.wants/sys-fs-fuse-connections.mount 19 | - /lib/systemd/system/sysinit.target.wants/sys-kernel-config.mount 20 | - /lib/systemd/system/sysinit.target.wants/sys-kernel-debug.mount 21 | - /lib/systemd/system/sysinit.target.wants/systemd-ask-password-console.path 22 | - /lib/systemd/system/sysinit.target.wants/systemd-binfmt.service 23 | - /lib/systemd/system/sysinit.target.wants/systemd-hwdb-update.service 24 | - /lib/systemd/system/sysinit.target.wants/systemd-journal-flush.service 25 | - /lib/systemd/system/sysinit.target.wants/systemd-journald.service 26 | - /lib/systemd/system/sysinit.target.wants/systemd-machine-id-commit.service 27 | - /lib/systemd/system/sysinit.target.wants/systemd-modules-load.service 28 | - /lib/systemd/system/sysinit.target.wants/systemd-random-seed.service 29 | - /lib/systemd/system/sysinit.target.wants/systemd-sysctl.service 30 | - /lib/systemd/system/sysinit.target.wants/systemd-tmpfiles-setup-dev.service 31 | - /lib/systemd/system/sysinit.target.wants/systemd-udev-trigger.service 32 | - /lib/systemd/system/sysinit.target.wants/systemd-udevd.service 33 | - /lib/systemd/system/sysinit.target.wants/systemd-update-utmp.service 34 | - /lib/systemd/system/sockets.target.wants/systemd-udevd-control.socket 35 | - /lib/systemd/system/sockets.target.wants/systemd-udevd-kernel.socket 36 | 37 | - name: Set multi-user as default runlevel 38 | command: systemctl set-default multi-user.target 39 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install Administrator PGP keys 2 | block: 3 | - name: create temporary build directory 4 | ansible.builtin.tempfile: 5 | state: directory 6 | register: gnupghome 7 | check_mode: no 8 | changed_when: False 9 | - name: create root .ssh directory 10 | file: 11 | path: /root/.ssh 12 | state: directory 13 | mode: "0700" 14 | - name: create hashbang lib directory 15 | file: 16 | path: /var/lib/hashbang 17 | state: directory 18 | - name: Copy administrator PGP keys 19 | shell: 20 | cmd: | 21 | set -e 22 | export GNUPGHOME=$(mktemp -d) 23 | KEYRING_DIR=/var/lib/hashbang/keyring 24 | cat > "${GNUPGHOME}/gpg.conf" << EOF 25 | # Never, ever, ever do this in your personal gpg.conf 26 | # However, this is sane when you know you use an empty GNUPGHOME 27 | keyring /var/lib/hashbang/admins.gpg 28 | trust-model always 29 | EOF 30 | 31 | if ! test -d $KEYRING_DIR; then 32 | git clone --recursive https://github.com/hashbang/keyring $KEYRING_DIR 33 | else 34 | git -C $KEYRING_DIR fetch 35 | git -C $KEYRING_DIR verify-commit origin/master 36 | git -C $KEYRING_DIR merge --ff-only origin/master 37 | fi 38 | - name: Find copied admin keys 39 | find: 40 | paths: /var/lib/hashbang/keyring/admins 41 | register: admin_keys 42 | - name: Import admin keys into temporary keyring and add to root ssh authorized_keys 43 | shell: | 44 | gpg --homedir {{ gnupghome.path }} --import {{ item.path }} 45 | keyid=$(gpg --dry-run --with-colons --show-keys {{ item.path }} \ 46 | | awk -F: '/^fpr:/ { print $10; exit; }') 47 | sshkey=$(gpg --homedir {{ gnupghome.path }} --export-ssh-key $keyid) 48 | if ! grep -q "$sshkey" /root/.ssh/authorized_keys; then 49 | echo "$sshkey" | tee -a /root/.ssh/authorized_keys 50 | fi 51 | with_items: "{{ admin_keys.files }}" 52 | changed_when: False # temporary build directory 53 | - name: Export administrator pgp keys to combined keychain file 54 | shell: | 55 | gpg \ 56 | --homedir {{ gnupghome.path }} \ 57 | -q \ 58 | --batch \ 59 | --yes \ 60 | --export \ 61 | --export-options export-clean,export-minimal \ 62 | -o /var/lib/hashbang/admins.gpg 63 | args: 64 | executable: /bin/bash 65 | - file: 66 | path: /var/lib/hashbang/admins.gpg 67 | mode: "0644" 68 | 69 | - name: Install trusted author PGP keys 70 | block: 71 | - file: 72 | path: /etc/ansible/keys/gnupg 73 | state: directory 74 | mode: 0700 75 | - shell: | 76 | GNUPGHOME=/etc/ansible/keys/gnupg \ 77 | gpg --import /var/lib/hashbang/admins.gpg 78 | args: 79 | executable: /bin/bash 80 | 81 | - name: Install ansible-pull config 82 | copy: 83 | dest: /etc/ansible/ansible-pull.env 84 | content: | 85 | GIT_REPO=https://github.com/hashbang/shell-server.git 86 | GIT_BRANCH=master 87 | GIT_PATH=/etc/ansible/repos/shell-server 88 | PLAYBOOK_FILE=/etc/ansible/repos/shell-server/ansible/main.yml 89 | GNUPGHOME=/etc/ansible/keys/gnupg/ 90 | ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp 91 | ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp 92 | 93 | - name: Install ansible-pull as systemd timer 94 | block: 95 | - copy: 96 | dest: /etc/systemd/system/ansible-pull.service 97 | content: | 98 | [Unit] 99 | Description=Run ansible-pull 100 | After=network.target 101 | 102 | [Service] 103 | EnvironmentFile=/etc/ansible/ansible-pull.env 104 | ExecStart=/bin/bash -c "/usr/bin/ansible-pull \ 105 | -U $GIT_REPO \ 106 | -C $GIT_BRANCH \ 107 | -d $GIT_PATH \ 108 | -c local \ 109 | -i '%H,' \ 110 | --verify-commit \ 111 | $PLAYBOOK_FILE" 112 | Type=oneshot 113 | 114 | [Install] 115 | WantedBy=multi-user.target 116 | - copy: 117 | dest: /etc/systemd/system/ansible-pull.timer 118 | content: | 119 | [Unit] 120 | Description=Run ansible-pull every 15 mins 121 | 122 | [Timer] 123 | OnBootSec=15min 124 | OnUnitInactiveSec=15m 125 | 126 | [Install] 127 | WantedBy=timers.target 128 | - systemd: 129 | name: ansible-pull.timer 130 | state: started 131 | enabled: yes 132 | daemon_reload: yes 133 | ignore_errors: yes 134 | 135 | - name: Automatically ban users running open proxies 136 | block: 137 | - name: Install auto-banner 138 | copy: 139 | dest: /usr/local/bin/autoban 140 | mode: "0755" 141 | content: | 142 | #!/bin/sh 143 | for addr_family in 4 6; do 144 | netstat -tulpn -${addr_family} | grep -v -e mosh -e syncthing -e weechat -e 127.0.0.1 | awk '{ print $4 }' | rev | cut -d: -f1 | rev | sort -un | uniq | while read port; do 145 | for protocol in http https socks4 socks5; do 146 | if timeout 1 curl -${addr_family} -s --proxy "${protocol}://localhost:${port}/" http://example.com | grep "Example Domain" >/dev/null; then 147 | netstat -tulpn | awk '$4 ~ /'"$port"'/ { print $7 }' | cut -d/ -f1 | xargs ps -o user:30 -p | tail -n +2 | xargs echo loginctl terminate-user 148 | netstat -tulpn | awk '$4 ~ /'"$port"'/ { print $7 }' | cut -d/ -f1 | xargs ps -o user:30 -p | tail -n +2 | xargs loginctl kill-user 149 | fi 150 | done 151 | done 152 | done 153 | - name: Install systemd unit for autobanner 154 | copy: 155 | dest: /etc/systemd/system/autoban.service 156 | content: | 157 | [Unit] 158 | Description=Run autoban to clean up users running open proxies 159 | After=network.target 160 | 161 | [Service] 162 | ExecStart=/usr/local/bin/autoban 163 | Type=oneshot 164 | 165 | [Install] 166 | WantedBy=multi-user.target 167 | 168 | - name: Install systemd timer for autobanner 169 | copy: 170 | dest: /etc/systemd/system/autoban.timer 171 | content: | 172 | [Unit] 173 | Description=Run autoban every 5 minutes 174 | 175 | [Timer] 176 | OnBootSec=5min 177 | OnUnitInactiveSec=5min 178 | 179 | [Install] 180 | WantedBy=timers.target 181 | 182 | - name: Start autoban 183 | systemd: 184 | name: autoban.timer 185 | state: started 186 | enabled: yes 187 | daemon_reload: yes 188 | ignore_errors: yes 189 | 190 | - name: Install Welcome Templates and Man page 191 | block: 192 | - file: 193 | path: "/{{ item.path }}" 194 | state: directory 195 | mode: "0755" 196 | with_filetree: "tasks/hashbang/templates" 197 | when: item.state == 'directory' 198 | - template: 199 | src: "{{ item.src }}" 200 | dest: "/{{ item.path | regex_replace('.j2','') }}" 201 | mode: "{{ item.mode[1] == '7' and '0755' or '0644' }}" 202 | with_filetree: "tasks/hashbang/templates" 203 | when: item.state == 'file' 204 | 205 | - name: Set welcome script executable 206 | file: dest=/etc/hashbang/welcome mode=a+x 207 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/hashbang/welcome.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat /etc/hashbang/welcome.pre 4 | 5 | if [ -n "$TMUX" ]; then 6 | sed "s/\\\$USER/${USER}/" /etc/hashbang/welcome.tmux 7 | else 8 | sed "s/\\\$USER/${USER}/" /etc/hashbang/welcome.notmux 9 | fi 10 | 11 | cat /etc/hashbang/welcome.post 12 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/hashbang/welcome.notmux.j2: -------------------------------------------------------------------------------- 1 | Things to explore: 2 | 3 | * You can start 'tmux' to enter a tmux session. 4 | Help will be displayed when tmux is started. 5 | 6 | * You can resume a detached tmux session at any time. 7 | Use 'tmux attach' to resume your tmux session. 8 | 9 | * Your Hashbang email address is $USER@hashbang.sh 10 | The `mutt` email client is preconfigured for you. 11 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/hashbang/welcome.post.j2: -------------------------------------------------------------------------------- 1 | * To learn more about us and our offerings type: man hashbang 2 | 3 | Like what we're doing? Consider donating to expand our efforts. 4 | * Bitcoin - [ 1DtTvCLiUMhs21QcETQzLyiqxoopUjqBSU ] 5 | * Google Wallet - [ donate@hashbang.sh ] 6 | * PayPal - [ http://goo.gl/aSQWy0 ] 7 | 8 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/hashbang/welcome.pre.j2: -------------------------------------------------------------------------------- 1 | _ _ __ 2 | _| || |_ | | Welcome to #!. This network has three rules: 3 | |_ __ _|| | 4 | _| || |_ | | 1. When people need help, teach. Don't do it for them 5 | |_ __ _||__| 2. Don't use our resources for closed source projects 6 | |_||_| (__) 3. Be excellent to each other 7 | 8 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/hashbang/welcome.tmux.j2: -------------------------------------------------------------------------------- 1 | Things to explore: 2 | 3 | * You are in a 'tmux' session. There are three tabs below. 4 | Navigate with + a tab number. 5 | 6 | * You are already in our IRC channel in "tab 1" 7 | Type + 1 to reach it and chat with us. 8 | 9 | * Your Hashbang email address is: $USER@hashbang.sh 10 | Type + 2 to check your emails in mutt 11 | 12 | * You can detach from this tmux session with + 13 | You can also re-attach outside of tmux with 'tmux attach' 14 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/etc/skel/Mail/new/msg.welcome.j2: -------------------------------------------------------------------------------- 1 | From: noreply@hashbang.sh 2 | X-Original-To: {username}@hashbang.sh 3 | Delivered-To: {username}@hashbang.sh 4 | MIME-Version: 1.0 5 | From: The Local Bot 6 | Date: {date} 7 | Subject: Press Enter to open this! 8 | To: {username} <{username}@hashbang.sh> 9 | Content-Type: text/plain 10 | 11 | Hey! Welcome to #! 12 | 13 | Hashbang (The name of the #! symbol) is a community-run online "hackerspace" based off of the core principle of "Teach. Learn. Make things do." We are a community dedicated to helping, teaching, and providing people with resources for educational and productive services. With this in mind, Hashbang (while being called an online hackerspace) does not support nor does it encourage the engagement of illegal or otherwise disruptive activities that may have a negative impact on the resources of other users. 14 | 15 | The name of hashbang is based off of the symbol '#!', found at the start of a shell script. This symbol instructs the operating system what program is required to "do" something with the code. Hashbang runs the same way. We try to instruct our users on the tools and skills required to -do- whatever they want for themselves. Likewise if you want something done, -do- it yourself. Don't know how? Ask. We're here to help new people get used to a Linux/Unix environment and to start them off with making software, learning how the terminal and services work... or perhaps helping talk through a challenging work problem someone faces at a major tech company. We welcome all skill levels and backgrounds. 16 | 17 | Software is almost never complete, and there might always be something off. Being a community-run service, hashbang encourages users to find bugs within the software and attempt to fix them. Most of our repositories are stored online on GitHub (https://github.com/hashbang) and are easily accessible. If you have any questions about any of our offerings, or just want to chat, you can switch to the first window (ctrl-B then 1) and talk to a number of other users in real time. 18 | 19 | Thank you for taking the time to read this welcome message, and welcome to #! 20 | 21 | To find out more try 'man hashbang' on one of the terminal tabs [ c ] 22 | 23 | Currently, the ~/Public folder isn't exposed over HTTP by default; 24 | however, users can use the `SimpleHTTPServer.service` systemd unit file (in `~/.config/systemd/user`, modify it to set port) or a `@reboot` crontab entry to run `python3 -m http.server ` to provide a webserver exposing it. 25 | 26 | This message will self-destruct in 10 seconds. 27 | -------------------------------------------------------------------------------- /ansible/tasks/hashbang/templates/usr/local/share/man/man7/hashbang.7.j2: -------------------------------------------------------------------------------- 1 | .\" Man page for hashbang 2 | .TH man 7 "29 May 2014" "0.5" "#! man page" 3 | 4 | .SH NAME 5 | #! \- "shell" service and collective of awesome people. 6 | 7 | .SH SYNOPSIS 8 | 9 | bash <(curl hashbang.sh) 10 | 11 | .SH DESCRIPTION 12 | 13 | We are a diverse community of people who love teaching and learning. 14 | Putting a #! at the beginning of a "script" style program tells a computer that 15 | it needs to "do something" or "execute" the file. Likewise, we are a community 16 | of people that like to "do stuff". 17 | 18 | If you like technology and want to learn to write your first program, learn to 19 | use Linux, or even take on interesting challenges with some of the best in 20 | the industry, you are in the right place. 21 | .SH EXAMPLES 22 | .TP 23 | 24 | .BI ssh\ someuser@hashbang.sh 25 | Use the "ssh" command to get yourself back into your account from any computer 26 | that has your private key. 27 | .TP 28 | .BI cat\ foo 29 | echo the foo file to the console 30 | 31 | .SH AVAILABLE SOFTWARE 32 | .SS Account Management 33 | ssh hashbang.sh - interactive ssh application to manage keys, default shell, 34 | user configuration, etc 35 | .SS Compilers / Interpreters / Programming Languages 36 | perl - A high-level, general-purpose dynamic programming language. Commonly 37 | referred to as "the duct tape of the internet." 38 | 39 | python - A high-level, general-purpose programming language that emphasizes 40 | code readability. 41 | 42 | ruby - A dynamic, object-oriented general-purpose programming language. 43 | 44 | haskell [ghc] - A standardized, general-purpose programming language with non-strict 45 | semantics and strong static typing. 46 | 47 | lua - A lightweight multi-paradigm programming language designed as a scripting 48 | language. 49 | 50 | clojure - A general-purpose programming language with an emphasis on functional 51 | programming. It is a dialect of the Lisp programming language. 52 | 53 | go - A statically-typed language developed at Google with syntax loosely derived from C with 54 | garbage collection. 55 | 56 | nodejs - A cross-platform runtime environment for server-side and network 57 | applications written in javascript. 58 | 59 | sbcl - (Steel Bank Common Lisp) A Lisp implementation that features a high 60 | performance native compiler, Unicode support, and threading. 61 | 62 | ghc - (The Glorious Glasgow Haskell Compilation System) a native code compiler 63 | for Haskell. 64 | 65 | gcc - (GNU Compiler Collection) A compiler system that supports C, C++ and 66 | various other programming languages. 67 | .SS Text Editors 68 | vim - A popular vi clone and the IDE of choice of most of the #! regulars. 69 | Ships by default on all operating systems that matter. 70 | 71 | emacs - A very capable scriptable text editor also capable of being a full IDE 72 | with all the power of vim implemented in different ways. Not in as wide of 73 | use as it once was but plenty of skilled hackers still swear by it. 74 | 75 | nano - A text editor that emulates the Pico text editor and is part of the GNU 76 | Project. 77 | 78 | joe - (Joe's Own Editor) a text editor designed for ease of use. 79 | 80 | pico - (Pine Composer) a text editor originally integrated with the pine e-mail 81 | client and designed at the Office of Computing and Communications at the 82 | University of Washington. 83 | 84 | mcedit - Internal text editor for the Midnight Commander file manager. 85 | 86 | zile - An Emacs like text editor that is less resource intensive. 87 | .SS Password Management 88 | pass - A shell based password manager. 89 | .SS Cryptography / Hashing 90 | encfs - A FUSE-based cryptographic filesystem that transparently encrypts files 91 | using an arbitrary directory as storage for the encrypted files. 92 | 93 | gpg - (GNU Privacy Guard) A GPL Licensed alternative to the PGP suite of 94 | cryptographic software compliant with RFC 4880. 95 | 96 | md5sum - Calculates and verifies 128-bit MD5 hashes as described in RFC 1321. 97 | 98 | shasum - Calculates and verifies SHA hashes. 99 | 100 | bcrypt - A key derivation function for passwords based on the Blowfish cipher. 101 | .SS Time Management 102 | calendar - Checks current directory or CALENDAR_DIR environment variable for a 103 | file named calendar and displays appointments and reminders. 104 | 105 | remind - A sophisticated reminder service. 106 | 107 | wyrd - A text-based front-end to the Remind program. 108 | 109 | tudu - A command-line tool to manage TODO lists hierarchically. 110 | .SS Shells 111 | bash - (Bourne Again Shell) The standard shell on most Linux and unix-like 112 | systems which is a GNU replacement for the Unix Bourne shell. A linux classic 113 | brah. 114 | 115 | zsh - (Z Shell) An extension of the Bourne shell extended with features from 116 | ksh and tcsh. 117 | 118 | fish - (Friendly Interactive Shell) An attempt to make a more interactive, 119 | user-friendly shell. 120 | 121 | ksh - (Korn Shell) A shell backwards compatible with the Bourne shell but also 122 | includes many features of the C shell. 123 | .SS Email 124 | mutt - A text-based email client. "All mail clients suck. This one just sucks 125 | less." 126 | .SS Math 127 | units - Unit conversion utility. 128 | 129 | dc - A reverse-polish desk calculator which supports arbitrary-precision 130 | arithmetic. 131 | 132 | qalc - A small simple to use command-line calculator. 133 | 134 | bc - An arbitrary precision calculator language 135 | 136 | .SS Chat / IM 137 | weechat-curses - Wee Enhanced Environment for Chat (Curses version) 138 | 139 | irssi - A text-based IRC client written in the C programming language. 140 | 141 | bitlbee - Bitlbee brings Instant Messaging to IRC clients. It has support for 142 | multiple IM networks/protocols including Google Talk. 143 | 144 | .RS 145 | To use bitlbee in weechat enter 146 | .RS 147 | .B 148 | /server add bitlbee irc.hashbang.sh/6610 149 | .RE 150 | then 151 | .RS 152 | .B 153 | /connect bitlbee 154 | .RE 155 | this will force join you into the 156 | .B 157 | &bitlbee 158 | channel. If you are interested in using Google Talk follow this guide 159 | http://wiki.bitlbee.org/HowtoGtalk 160 | .RE 161 | 162 | .SS Web Browsing 163 | elinks - Similar to links, but also supports Form Input, Password Management, 164 | and Tabbed Browsing 165 | 166 | lynx - A general purpose distributed information web browser. 167 | 168 | w3m - A text based web browser and pager. 169 | 170 | html2text - Reads an HTML document and outputs plain text characters. 171 | .SS Database 172 | redis [redis-*] - A networked, in-memory, key-value data store with optional durability 173 | written in ANSI C. 174 | .SS File Management 175 | mc - (Midnight Commander) A text-based file manager similar to Norton 176 | Commander. 177 | 178 | scp - (Secure Copy) A client that uses the Secure Shell protocol to securely 179 | transfer files between hosts. 180 | 181 | rsync - A file synchronization and file transfer program that minimizes network 182 | data transfer by using a form of delta encoding called the rsync algorithm. 183 | 184 | duplicity - A software suite that provides encrypted, digitally signed, 185 | versioned, remote backups of files. 186 | 187 | ranger - A text-based file manager written in Python. 188 | 189 | du - (disc usage) Estimates file space usage on a filesystem. 190 | 191 | ncdu - A simple ncurses disk usage analyzer. 192 | 193 | stow - A symlink manager. Helpful for managing several locally-installed things. 194 | 195 | find - Used to search the filesystem for a particular file. 196 | 197 | locate - Searches a prebuilt database for files on a filesystem. 198 | 199 | tree - A recursive directory listing program that produces a depth-indented 200 | listing of files. 201 | .SS Archiving 202 | atool - A script for managing file archives of various types. 203 | 204 | zip - A PKZIP compatible compression and file packaging utility. 205 | 206 | unzip - Utility for uncompressing PKZIP compressed files. 207 | 208 | p7zip - A program for compressing and uncompressing 7-zip compressed files. 209 | 210 | tar - Utility used for compressing and uncompressing tar files. 211 | 212 | gzip - An application used to create gzip compressed files. 213 | 214 | zpaq - A program for creating journaling or append-only compression files. 215 | .SS Network 216 | iperf - A bandwidth measurement utility. 217 | 218 | nmap - (Network Mapper) A security scanner used to discover hosts and services 219 | on a computer network. 220 | 221 | mtr - (Matt's TraceRoute) Combines the functionality of the traceroute and ping 222 | programs in a single network diagnostic tool. 223 | 224 | telnet - Used to communicate with another host using the telnet protocol. 225 | 226 | ssh - A client used to connect to a host using the Secure Shell protocol. 227 | 228 | siege - A multi-threaded http load testing and benchmarking utility. 229 | 230 | tsung - A tool to stress test HTTP, WebDAV, SOAP, PostgreSQL, MySQL, AMQP, MQTT 231 | and XMPP servers. 232 | 233 | lftp - A file transfer program that allows sophisticated ftp, http and other 234 | connections to other hosts. 235 | 236 | curl - A tool used to transfer data from or to a server using HTTP, HTTPS, FTP, 237 | FTPS, SCP, SFTP, TFTP, DICT, TELNET, LDAP or FILE). 238 | 239 | aria2 [aria2c] - A utility for downloading files via HTTP(S), FTP, BitTorrent, and 240 | Metalink. 241 | 242 | ipcalc - A program that calculates IP information for a host. 243 | 244 | socat - (SOcket CAT) A command line based utility that establishes two 245 | bidirectional byte streams and transfers data between them. 246 | 247 | netcat - A networking utility which reads and writes data across networks from 248 | the command line. 249 | 250 | ssh-copy-id - A script that uses SSH to copy a public key to a remote machine's 251 | authorized_keys. 252 | .SS Image Tools 253 | imagemagick [convert, mogrify, ...] - A software suits used to create, edit, and compose bitmap images. 254 | 255 | .SS Code Management 256 | cvs - (Concurrent Versions System) A revision control system using 257 | client-server architecture. 258 | 259 | svn - (Subversion) A software versioning and revision control system 260 | maintained by apache and designed as a successor to CVS 261 | 262 | mercurial [hg] - A distributed revision control system designed for high 263 | performance, scalability, and decentralization. 264 | 265 | git - A distributed version control system with an emphasis on speed, data 266 | integrity, and support for distributed, non-linear workflows. 267 | 268 | tig - A text-mode interface for git. 269 | 270 | cloc - Counts and computes differences of lines of source code and comments. 271 | 272 | diff - Compares files line by line. 273 | 274 | vimdiff - Edits 2 - 4 versions of a file with vim while showing differences. 275 | 276 | ctags - A programming tool that generates an index file of names found in 277 | source and header files of various programming languages. 278 | 279 | cmake - Software for managing the build process of software using a 280 | compiler-independent method. 281 | 282 | shellcheck - Linter for shell scripts 283 | .SS Games/Toys 284 | 285 | nethack - A roguelike game descended from the game Hack and Rogue. 286 | 287 | slashem - (Super Lotsa Added Stuff Hack - Extended Magic) is a variant of the 288 | roguelike game NetHack that offers extra features, monsters, and items. 289 | 290 | frotz - An interpreter for Infocom games and other z-machine games. 291 | 292 | bsdgames [adventure, ...] - A collection of text games from BSD systems. 293 | 294 | bastet - (Bastard Tetris) A Tetris clone. 295 | 296 | gnugo - Open source implementation of the game Go. 297 | 298 | gnuchess - Chess 299 | .SS System Management Utilities 300 | htop - An interactive system-monitor process-viewer. 301 | 302 | strace - Application for tracing system calls and signals. 303 | 304 | command-not-found - (Debian) Suggest a package when the user calls a command 305 | that could not be found. 306 | 307 | .SS Window/Session Managers 308 | 309 | tmux - An Application used to multiplex several virtual consoles, allowing a 310 | user to access multiple separate terminal sessions inside a single terminal. 311 | 312 | screen - Application used to multiplex several virtual consoles, allowing a 313 | user to access multiple separate terminal sessions in a single terminal. 314 | 315 | byobu - An enhancement for the terminal multiplexers Screen or Tmux that can be 316 | used to provide on screen notification or status as well as tabbed multi-window 317 | management. 318 | .SS Misc. / Unsorted (Sort these!) 319 | pv - Monitors the progress of data through a pipe. 320 | 321 | xargs - Used to build and execute command lines from standard input. 322 | 323 | parallel - Shell tool for executing jobs in parallel using one or more 324 | computers. 325 | 326 | ag - A significantly faster replacement to ACK with a built in VCS. 327 | 328 | watch - Executes a program periodically, showing the output fullscreen. 329 | 330 | libev - A high-performance event loop for C. 331 | 332 | libevent - Provides a mechanism to execute a callback function when a specific 333 | event occurs on a file descriptor or after a timeout has been reached. 334 | 335 | cowsay - Generates ASCII pictures of a cow with a message. 336 | 337 | dos2unix - Converts line breaks in a text file from DOS format to Unix format. 338 | 339 | unix2dos - Converts line breaks in a text file from Unix format to DOS format. 340 | .SH HISTORY 341 | 2004 - lrvick secured free-for-all usage of a dedicated server, hosted at 342 | "The Planet" datacenter in Austin, TX, in exchange for providing free system 343 | administration services to an educational web application provider. He 344 | distributed shell accounts to a group of friends for personal projects, 345 | organizing resources and efforts via IRC. 346 | 347 | 2006 - Having outgrown the shared server, the community opted to invest in our 348 | own dedicated server, lovingly named "Adam". All projects were migrated over, 349 | and a few months later "Eve" was added for redundancy and to minimize downtime. 350 | These were hosted at SiteGenie in Rochester, MN. 351 | 352 | 2008 - As a hosting service, we hosted many web projects visited by hundreds of 353 | thousands of users, in addition to seeing hundreds of users on our IRC and 354 | shell services. Our community was known in multiple IRC circles to have very 355 | well-developed overall system security, and we regularly dealt with various 356 | types of attacks trying to break through. A "Script Kiddie" named Piratox, 357 | unable to break in through any usual methods, opted to make use of a large 358 | botnet, disrupting us with a large scale DDOS attack. 359 | 360 | The attack was significant enough that the entire SiteGenie datacenter was 361 | taken offline. Though we tracked down Piratox and ended the dispute, SiteGenie 362 | was unprepared to deal with the possibility of further DDOS attacks of similar 363 | scale and promptly ended our contract. They generously offered to overnight our 364 | hard drives to any location we chose. Seeing the potential in this, we involved 365 | it in the backup plans that had already been set in motion. 366 | 367 | Echelon, a volunteer admin, brought "Noah" online in his Ohio basement. 368 | Bluescales, another volunteer admin, rushed to setup a VPS in a Montana 369 | Datacenter. He dubbed it "Moses". We quickly routed essential services from 370 | backups between the two servers while one of the two backup drives containing 371 | user files was overnighted to Noah. Shell user files were available to our 372 | community again within 24 hours. 373 | 374 | With emergency options in place, we sought a new primary server. After 375 | reviewing our budget and options, we opted for a dedicated server at a newer 376 | company, VolumeDrive, in Wilkes Barre, Pennsylvania. We took a chance on them 377 | due to their reputation for inexpensive, unmetered bandwidth plans with 378 | regular bandwidth testing. "Melchiz" was born, and quickly became responsible 379 | for community services including shells, email, and IRC, as well as hosting 380 | most smaller websites. 381 | 382 | VolumeDrive was a good fit for most of our services; however, like SiteGenie, 383 | they were unwilling to deal with the unwanted attention that our historical 384 | reputation could bring. To address this, we deployed "Samson" in an undisclosed 385 | location, ensuring it would be difficult to target by disruptive parties. 386 | "Gideon" was deployed in Germany as a dumb proxy to more reliably protect 387 | Samson's location. Were it to ever go down, more could rapidly take its place. 388 | We felt really good about the maintainability of this setup. 389 | 390 | 2010 - Samson needed a kernel update to address security issues that had 391 | recently come to light. One of our volunteer admins, Viaken, decided to take on 392 | the kernel update on his own, but did not include the correct SATA driver. On 393 | reboot, Samson experienced a kernel panic. Per a special agreement with the 394 | datacenter, hosting was available and free so long as support was never 395 | contacted. Thus, Samson was to remain frozen at a kernel panic screen, and 396 | may still be hung there to this day. Gideon, now purposeless, was taken 397 | offline shortly thereafter. 398 | 399 | We were left with no choice but to risk hosting all services on Melchiz until 400 | a better solution could be secured. 401 | 402 | 2013 - After frequent downtime and multiple disputes with VolumeDrive 403 | (including a case where they mistakenly formatted one of our production hard 404 | drives), our community sought to "go big or go home". We went big and secured 405 | the dedicated server "Og". Og's specs were more than overkill for everything 406 | we provided, but we knew it would be worth it for our long-term goals of 407 | expanding our free community offerings to the general public. 408 | 409 | 2014 - #! shells are now available to the general public. Welcome! 410 | 411 | 412 | .SH You can help! 413 | 414 | Fork, make changes, and submit Github Pull Requests here: 415 | 416 | https://github.com/hashbang/shell-server/ 417 | 418 | This man file can be updated here: 419 | 420 | https://github.com/hashbang/shell-server/blob/master/ansible/tasks/hashbang/templates/usr/local/share/man/man7/hashbang.7.j2 421 | -------------------------------------------------------------------------------- /ansible/tasks/logging/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure journald 3 | copy: 4 | dest: /etc/journald.conf 5 | content: | 6 | [Journal] 7 | MaxLevelStore=notice 8 | MaxRetentionSec=1month 9 | SystemMaxUse=1G 10 | -------------------------------------------------------------------------------- /ansible/tasks/mail/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install mail packages 3 | apt: 4 | update_cache: yes 5 | name: 6 | - postfix 7 | - procmail 8 | - msmtp 9 | 10 | - name: Update postfix to relay mail 11 | block: 12 | - name: Ensure postfix directory exists 13 | file: path=/etc/postfix state=directory 14 | - name: Setup main postfix dynamic maps 15 | lineinfile: 16 | path: /etc/postfix/dynamicmaps.cf 17 | line: "ldap /usr/lib/postfix/dict_ldap.so dict_ldap_open" 18 | - name: Setup main postfix main config 19 | copy: 20 | dest: /etc/postfix/main.cf 21 | content: | 22 | smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) 23 | biff = no 24 | append_dot_mydomain = no 25 | readme_directory = no 26 | compatibility_level = 2 27 | 28 | # We serve mail for hashbang.sh only 29 | mydomain = hashbang.sh 30 | myorigin = $mydomain 31 | mydestination = $myhostname 32 | alias_maps = hash:/etc/aliases 33 | 34 | # Relay settings 35 | relayhost = mail.$mydomain 36 | smtp_tls_security_level = secure 37 | smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt 38 | smtp_tls_fingerprint_digest = sha1 39 | smtp_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1 40 | smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1 41 | smtp_tls_exclude_ciphers = NULL, MD5, DES, RC4 42 | smtp_tls_mandatory_ciphers = high 43 | tls_high_cipherlist = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 44 | 45 | # TLS Settings 46 | smtpd_use_tls = yes 47 | smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem 48 | smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key 49 | smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache 50 | smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache 51 | 52 | # Delivery configuration 53 | mailbox_command = procmail -a "$EXTENSION" 54 | mailbox_size_limit = 0 55 | message_size_limit = 52428800 56 | recipient_delimiter = + 57 | 58 | # Access restrictions 59 | authorized_flush_users = root 60 | authorized_mailq_users = root 61 | 62 | - name: Setup procmail to use homedir mail folder 63 | copy: 64 | dest: /etc/procmailrc 65 | content: | 66 | ORGMAIL=${HOME}/Mail/new 67 | DEFAULT=${ORGMAIL} 68 | 69 | - name: Update pam to set maildir to ~/Mail 70 | block: 71 | - name: Update maildir for console login 72 | lineinfile: 73 | path: /etc/pam.d/login 74 | regexp: "^session +optional +pam_mail.so" 75 | line: "session optional pam_mail.so dir=~/Mail standard" 76 | - name: Update maildir for sshd login 77 | lineinfile: 78 | path: /etc/pam.d/sshd 79 | regexp: "^session +optional +pam_mail.so" 80 | line: "session optional pam_mail.so dir=~/Mail standard noenv" 81 | 82 | - name: Setup msmtprc for hashbang smtp 83 | copy: 84 | dest: /etc/msmtprc 85 | content: | 86 | # Global defaults 87 | defaults 88 | aliases /etc/aliases 89 | logfile ~/.msmtp.log 90 | 91 | # Hashbang account 92 | # Required for msmtp to function as sendmail 93 | account hashbang.sh 94 | host mail.hashbang.sh 95 | 96 | # Sender address 97 | auto_from on 98 | maildomain hashbang.sh 99 | 100 | # TLS configuration 101 | tls on 102 | tls_trust_file /etc/ssl/certs/ca-certificates.crt 103 | 104 | # Syslog logging with facility LOG_MAIL instead of the default LOG_USER. 105 | # Only applies to the #! account 106 | syslog LOG_MAIL 107 | 108 | # Make hashbang the default account 109 | account default : hashbang.sh 110 | 111 | - name: Update mailname to hashbang 112 | lineinfile: 113 | create: true 114 | path: /etc/mailname 115 | line: "hashbang.sh" 116 | 117 | - name: Install Postfix Aliases 118 | lineinfile: 119 | path: /etc/aliases 120 | line: 'root: root@hashbang.sh' 121 | -------------------------------------------------------------------------------- /ansible/tasks/misc/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set default locale to en_US.UTF-8 3 | lineinfile: 4 | path: /etc/default/locale 5 | regexp: "^LANG" 6 | line: "LANG=en_US.UTF8" 7 | 8 | - name: Set default timezone to UTC 9 | copy: 10 | dest: /etc/timezone 11 | content: "Etc/UTC" 12 | 13 | - name: Set up filesystem checking at boot to automatically fix errors 14 | lineinfile: 15 | path: /etc/default/rcS 16 | regexp: "FSCKFIX" 17 | line: "FSCKFIX=yes" 18 | 19 | - name: Install disk repartitioning script 20 | copy: 21 | dest: /etc/initramfs-tools/scripts/repartition-drive 22 | content: | 23 | #!/bin/bash 24 | 25 | mount | grep /dev/sda && echo "/dev/sda mounted. Aborting" && exit 26 | test -e /dev/sda2 && echo "/dev/sda2 already exists. Aborting" && exit 27 | 28 | mkdir /mnt 29 | modprobe ext4 30 | mount /dev/sda1 /mnt 31 | cp -R /mnt/lib / 32 | cp -R /mnt/lib64 / 33 | cp -R /mnt/bin / 34 | cp -R /mnt/sbin / 35 | cp -R /mnt/usr / 36 | umount /dev/sda1 37 | e2fsck -f /dev/sda1 38 | resize2fs /dev/sda1 20G 39 | echo -e "d\nn\n\n\n\n+20G\nn\np\n\n\n\nw\n" | fdisk /dev/sda 40 | mkfs.ext4 /dev/sda2 41 | 42 | - name: enable getty 43 | when: not dockerenv.stat.exists 44 | systemd: 45 | name: getty@tty1 46 | enabled: yes 47 | 48 | 49 | - name: Setup cron job to kill processes of stale accounts 50 | copy: 51 | dest: /etc/cron.daily/clean-lurkers 52 | content: | 53 | #!/bin/sh 54 | # See https://xkcd.com/686/ -- Admin mourning 55 | 56 | DAYS=30 57 | 58 | for range in 1000-59999 65536-4294967293; do 59 | for user in $(lastlog -b "$DAYS" -t "$((DAYS + 2))" -u "$range" | \ 60 | tail -n +2 | cut -d' ' -f1); do 61 | if [ ! -f "/home/${user}/.keep-account" ]; then 62 | loginctl terminate-user "$user" 63 | fi 64 | done 65 | done 66 | -------------------------------------------------------------------------------- /ansible/tasks/nginx/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install nginx 3 | apt: 4 | name: 5 | - nginx 6 | - libnginx-mod-stream 7 | 8 | - name: Setup sites-enabled/hashbang-http 9 | register: httpconf 10 | copy: 11 | dest: /etc/nginx/sites-enabled/hashbang-http 12 | content: | 13 | # Hashbang server configuration 14 | # ref: https://gist.github.com/RyanSquared/e59c7e274abef06e63b0e47e46997b00 15 | # 16 | map $http_upgrade $connection_upgrade { 17 | # An empty string indicates the header shouldn't be sent 18 | # causing the server to assume a keepalive (in HTTP/1.1) 19 | # See: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header 20 | default ''; 21 | WebSocket upgrade; 22 | } 23 | 24 | server { 25 | listen 80; 26 | listen [::]:80; 27 | 28 | server_name "~^(?[a-zA-Z0-9]+).{{ ansible_fqdn }}$"; 29 | 30 | location / { 31 | proxy_pass http://unix:/home/$user/.nginx.sock; 32 | proxy_http_version 1.1; # enable for keep-alive http support 33 | proxy_set_header Host $host; 34 | proxy_set_header X-Real-IP $remote_addr; 35 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 36 | 37 | # websocket support 38 | proxy_set_header Upgrade $http_upgrade; 39 | proxy_set_header Connection $connection_upgrade; 40 | } 41 | } 42 | 43 | server { 44 | listen 80; 45 | listen [::]:80; 46 | 47 | server_name "{{ ansible_fqdn }}"; 48 | 49 | location /metrics { 50 | proxy_pass http://localhost:9100/metrics; 51 | } 52 | } 53 | 54 | - name: Add SSL preread stream to nginx master config 55 | register: nginxconf 56 | blockinfile: 57 | path: /etc/nginx/nginx.conf 58 | marker: "# -- {mark} ANSIBLE MANAGED BLOCK -- ssl_preload blocks" 59 | block: | 60 | stream { 61 | map $ssl_preread_server_name $user_https { 62 | "~^(?[a-zA-Z0-9]+).{{ ansible_fqdn }}$" unix:/home/$user/.nginx.https.sock; 63 | } 64 | 65 | server { 66 | listen 443; 67 | listen [::]:443; 68 | ssl_preread on; 69 | proxy_pass $user_https; 70 | } 71 | } 72 | 73 | - name: Remove default nginx site 74 | file: 75 | state: absent 76 | path: /etc/nginx/sites-enabled/default 77 | 78 | - name: Restart nginx 79 | when: nginxconf.changed or httpconf.changed 80 | service: name=nginx state=restarted enabled=yes 81 | ignore_errors: yes # ignore error when systemd isn't running 82 | -------------------------------------------------------------------------------- /ansible/tasks/packages/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - apt_key: 3 | data: "{{ lookup('file', 'apt/weechat.asc') }}" 4 | id: 11E9DE8848F2B65222AA75B8D1820DB22A11534E 5 | keyring: /etc/apt/trusted.gpg.d/weechat.gpg 6 | 7 | - apt_repository: 8 | repo: deb https://weechat.org/debian {{ ansible_distribution_release }} main 9 | state: present 10 | filename: weechat 11 | 12 | - apt_repository: 13 | repo: deb-src https://weechat.org/debian {{ ansible_distribution_release }} main 14 | state: present 15 | filename: weechat 16 | 17 | - name: Upgrade existing packages 18 | apt: 19 | update_cache: yes 20 | upgrade: yes 21 | 22 | - name: Install all system packages 23 | apt: 24 | name: 25 | - acl 26 | - acpi 27 | - acpi-support-base 28 | - acpid 29 | - adduser 30 | - aglfn 31 | - alpine 32 | - anarchism 33 | - ansible 34 | - apt 35 | - apt-file 36 | - apt-transport-https 37 | - apt-utils 38 | - aptitude 39 | - aptitude-common 40 | - aria2 41 | - aspell 42 | - aspell-en 43 | - atool 44 | - auditd 45 | - autoconf 46 | - automake 47 | - autopoint 48 | - autotools-dev 49 | - awscli 50 | - base-files 51 | - base-passwd 52 | - bash 53 | - bash-completion 54 | - bastet 55 | - bc 56 | - bcrypt 57 | - binfmt-support 58 | - binutils 59 | - bitlbee 60 | - bitlbee-common 61 | - bsdgames 62 | - bsdmainutils 63 | - bsdutils 64 | - build-essential 65 | - busybox 66 | - byobu 67 | - bzip2 68 | - ca-certificates 69 | - cgroup-tools 70 | - checkpolicy 71 | - cloc 72 | - cloud-initramfs-dyn-netconf 73 | - cloud-initramfs-growroot 74 | - cloud-utils 75 | - cmake 76 | - cmake-data 77 | - command-not-found 78 | - console-setup 79 | - console-setup-linux 80 | - coreutils 81 | - cowsay 82 | - cpio 83 | - cpp 84 | - cracklib-runtime 85 | - cron 86 | - curl 87 | - cvs 88 | - dash 89 | - dbus 90 | - dbus-x11 91 | - dc 92 | - dconf-gsettings-backend 93 | - dconf-service 94 | - dctrl-tools 95 | - debconf 96 | - debconf-i18n 97 | - debconf-utils 98 | - debhelper 99 | - debian-archive-keyring 100 | - debian-keyring 101 | - debianutils 102 | - debsums 103 | - dehydrated 104 | - devscripts 105 | - dh-lua 106 | - dh-python 107 | - dictionaries-common 108 | - diffutils 109 | - dirmngr 110 | - discount 111 | - discover 112 | - discover-data 113 | - distro-info 114 | - distro-info-data 115 | - dmidecode 116 | - dmsetup 117 | - docutils-common 118 | - dos2unix 119 | - dpkg 120 | - dpkg-dev 121 | - duplicity 122 | - e2fslibs 123 | - e2fsprogs 124 | - eject 125 | - elinks 126 | - elinks-data 127 | - elixir 128 | - emacs-nox 129 | - emacsen-common 130 | - encfs 131 | - erlang-asn1 132 | - erlang-base 133 | - erlang-crypto 134 | - erlang-inets 135 | - erlang-mnesia 136 | - erlang-os-mon 137 | - erlang-public-key 138 | - erlang-runtime-tools 139 | - erlang-snmp 140 | - erlang-ssl 141 | - exuberant-ctags 142 | - fakeroot 143 | - ferm 144 | - figlet 145 | - file 146 | - findutils 147 | - firejail 148 | - fish 149 | - fish-common 150 | - fontconfig 151 | - fontconfig-config 152 | - fonts-dejavu-core 153 | - fonts-lyx 154 | - frotz 155 | - fuse 156 | - g++ 157 | - gawk 158 | - gcc 159 | - gconf-service 160 | - gconf2 161 | - gconf2-common 162 | - gdb 163 | - geoip-database 164 | - gettext 165 | - gettext-base 166 | - gforth 167 | - gforth-common 168 | - gforth-lib 169 | - ghc 170 | - gir1.2-glib-2.0 171 | - git-email 172 | - git-man 173 | - glances 174 | - glib-networking 175 | - glib-networking-common 176 | - glib-networking-services 177 | - gnuchess 178 | - gnugo 179 | - gnupg-agent 180 | - gnupg2 181 | - gnuplot-data 182 | - gnuplot-nox 183 | - golang-go 184 | - golang-src 185 | - gpgv 186 | - grep 187 | - groff-base 188 | - grub-common 189 | - grub-pc 190 | - grub-pc-bin 191 | - grub2-common 192 | - gsettings-desktop-schemas 193 | - gsfonts 194 | - guile-2.2 195 | - guile-2.2-dev 196 | - guile-2.2-libs 197 | - guile-3.0 198 | - guile-3.0-dev 199 | - guile-3.0-libs 200 | - gyp 201 | - gzip 202 | - haveged 203 | - hddtemp 204 | - hostname 205 | - html2text 206 | - htop 207 | - httpie 208 | - iamerican 209 | - ibritish 210 | - ieee-data 211 | - ienglish-common 212 | - ifupdown 213 | - imagemagick 214 | - imagemagick-6.q16 215 | - imagemagick-common 216 | - info 217 | - init 218 | - init-system-helpers 219 | - initramfs-tools 220 | - initscripts 221 | - insserv 222 | - install-info 223 | - installation-report 224 | - intltool-debian 225 | - iotop 226 | - ipcalc 227 | - iperf 228 | - iproute2 229 | - iptables 230 | - iputils-ping 231 | - ipxe-qemu 232 | - irssi 233 | - isc-dhcp-client 234 | - isc-dhcp-common 235 | - iso-codes 236 | - ispell 237 | - java-common 238 | - javascript-common 239 | - jekyll 240 | - joe 241 | - john 242 | - john-data 243 | - jq 244 | - kbd 245 | - kexec-tools 246 | - keyboard-configuration 247 | - klibc-utils 248 | - kmod 249 | - krb5-locales 250 | - ksh 251 | - ldap-utils 252 | - less 253 | - lftp 254 | - libcurl4-gnutls-dev 255 | - libpam-systemd 256 | - libsqlite3-dev 257 | - libxml2-utils 258 | - libnode-dev 259 | - linux-image-amd64 260 | - lm-sensors 261 | - locales 262 | - locales-all 263 | - locate 264 | - login 265 | - logrotate 266 | - lsb-base 267 | - lsb-release 268 | - lsof 269 | - ltrace 270 | - lua5.1 271 | - lua5.2 272 | - lua5.3 273 | - luajit 274 | - luarocks 275 | - lynx 276 | - m4 277 | - man-db 278 | - manpages 279 | - manpages-dev 280 | - mat 281 | - mawk 282 | - mc 283 | - mc-data 284 | - meson 285 | - mime-support 286 | - mksh 287 | - mlock 288 | - moreutils 289 | - mosh 290 | - mount 291 | - mtr 292 | - multiarch-support 293 | - mutt 294 | - mysql-common 295 | - nano 296 | - nasm 297 | - ncdu 298 | - ncurses-base 299 | - ncurses-bin 300 | - ncurses-doc 301 | - ncurses-term 302 | - net-tools 303 | - netbase 304 | - netcat-traditional 305 | - nethack-common 306 | - nethack-console 307 | - nfacct 308 | - ninja-build 309 | - node-abbrev 310 | - node-ansi 311 | - node-ansi-color-table 312 | - node-archy 313 | - node-async 314 | - node-block-stream 315 | - node-combined-stream 316 | - node-cookie-jar 317 | - node-delayed-stream 318 | - node-forever-agent 319 | - node-form-data 320 | - node-fstream 321 | - node-fstream-ignore 322 | - node-github-url-from-git 323 | - node-glob 324 | - node-graceful-fs 325 | - node-gyp 326 | - node-inherits 327 | - node-ini 328 | - node-json-stringify-safe 329 | - node-lockfile 330 | - node-lru-cache 331 | - node-mime 332 | - node-minimatch 333 | - node-mkdirp 334 | - node-mute-stream 335 | - node-node-uuid 336 | - node-nopt 337 | - node-normalize-package-data 338 | - node-npmlog 339 | - node-once 340 | - node-osenv 341 | - node-qs 342 | - node-read 343 | - node-read-package-json 344 | - node-request 345 | - node-retry 346 | - node-rimraf 347 | - node-semver 348 | - node-sha 349 | - node-sigmund 350 | - node-slide 351 | - node-tar 352 | - node-tunnel-agent 353 | - node-underscore 354 | - node-which 355 | - nodejs 356 | - npm 357 | - nscd 358 | - oidentd 359 | - openbios-ppc 360 | - openbios-sparc 361 | - openhackware 362 | - openssh-client 363 | - openssh-sftp-server 364 | - openssl 365 | - os-prober 366 | - p7zip 367 | - pandoc 368 | - pandoc-data 369 | - parallel 370 | - parted 371 | - pass 372 | - passwd 373 | - patch 374 | - pciutils 375 | - pep8 376 | - perl 377 | - perl-base 378 | - php-cgi 379 | - php-cli 380 | - php-common 381 | - php-curl 382 | - php-fpm 383 | - php-json 384 | - php-mysql 385 | - php-sqlite3 386 | - php-xml 387 | - pidgin-data 388 | - pinentry-curses 389 | - pkg-config 390 | - po-debconf 391 | - policykit-1 392 | - poppler-data 393 | - procps 394 | - psmisc 395 | - pv 396 | - pwgen 397 | - python3 398 | - python3-apt 399 | - python3-bottle 400 | - python3-chardet 401 | - python3-colorama 402 | - python3-decorator 403 | - python3-dev 404 | - python3-distlib 405 | - python3-html5lib 406 | - python3-jinja2 407 | - python3-markupsafe 408 | - python3-minimal 409 | - python3-numpy 410 | - python3-pip 411 | - python3-pkg-resources 412 | - python3-psutil 413 | - python3-py 414 | - python3-pyasn1 415 | - python3-pysnmp4 416 | - python3-reportbug 417 | - python3-requests 418 | - python3-scipy 419 | - python3-setuptools 420 | - python3-six 421 | - python3-software-properties 422 | - python3-urllib3 423 | - python3-venv 424 | - python3-virtualenv 425 | - python3-wheel 426 | - qalc 427 | - qemu-slof 428 | - qemu-system-common 429 | - qemu-user 430 | - qemu-utils 431 | - qprint 432 | - qtcore4-l10n 433 | - ranger 434 | - readline-common 435 | - redis-server 436 | - redis-tools 437 | - remind 438 | - reportbug 439 | - reptyr 440 | - resolvconf 441 | - ripgrep 442 | - rsync 443 | - rsyslog 444 | - rtorrent 445 | - ruby 446 | - rubygems-integration 447 | - samba-libs 448 | - sbcl 449 | - screen 450 | - seabios 451 | - sed 452 | - sensible-utils 453 | - sgml-base 454 | - shared-mime-info 455 | - shellcheck 456 | - siege 457 | - signing-party 458 | - silversearcher-ag 459 | - silversearcher-ag-el 460 | - slashem 461 | - slashem-common 462 | - socat 463 | - sqlite3 464 | - ssh 465 | - ssl-cert 466 | - startpar 467 | - stow 468 | - strace 469 | - subversion 470 | - swaks 471 | - sysstat 472 | - tar 473 | - task-english 474 | - tasksel 475 | - tasksel-data 476 | - tcl 477 | - tcl-tls 478 | - tcllib 479 | - tcpd 480 | - tcsh 481 | - telnet 482 | - tig 483 | - tmux 484 | - toilet 485 | - toilet-fonts 486 | - topgit 487 | - tor 488 | - traceroute 489 | - tree 490 | - tsung 491 | - tudu 492 | - tzdata 493 | - ucf 494 | - udev 495 | - units 496 | - unzip 497 | - urlview 498 | - usbutils 499 | - util-linux 500 | - util-linux-locales 501 | - valac 502 | - vim-common 503 | - vim-nox 504 | - vim-runtime 505 | - vim-tiny 506 | - virtualenv 507 | - w3m 508 | - wamerican 509 | - weechat 510 | - weechat-core 511 | - weechat-curses 512 | - weechat-lua 513 | - weechat-plugins 514 | - weechat-perl 515 | - weechat-python 516 | - wget 517 | - whiptail 518 | - whois 519 | - wyrd 520 | - xauth 521 | - xdg-user-dirs 522 | - xkb-data 523 | - xml-core 524 | - xz-utils 525 | - zile 526 | - zip 527 | - zlib1g 528 | - zlib1g-dev 529 | - znc 530 | - znc-dev 531 | - zpaq 532 | - zsh 533 | - zsh-common 534 | -------------------------------------------------------------------------------- /ansible/tasks/profile/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure PAM to create $HOME if it doesn't exist 3 | command: "pam-auth-update --package --enable mkhomedir" 4 | 5 | - name: Setup default user profile to use .local/bin in PATH 6 | copy: 7 | dest: /etc/profile.d/local_path.sh 8 | content: | 9 | export PATH="$HOME/.local/bin:$PATH" 10 | 11 | - name: Setup golang to use home directory dir 12 | copy: 13 | dest: /etc/profile.d/go.sh 14 | content: | 15 | export GOPATH="/usr/share/gocode:$HOME/.local/gocode" 16 | export PATH="$GOPATH/bin:$PATH" 17 | 18 | - name: Block wall messages from unprivileged users 19 | copy: 20 | dest: /etc/profile.d/wall.sh 21 | content: | 22 | mesg n 23 | 24 | - name: Setup zsh manpath 25 | copy: 26 | dest: /etc/profile.d/z_manpath.sh 27 | content: | 28 | export MANPATH="${MANPATH:-$(manpath)}" 29 | 30 | - name: Setup ruby to use home directory 31 | copy: 32 | dest: /etc/profile.d/ruby.sh 33 | content: | 34 | export PATH="$HOME/.gem/bin:$PATH" 35 | 36 | - name: Setup nvm to use home directory 37 | copy: 38 | dest: /etc/profile.d/nvm.sh 39 | content: | 40 | export NVM_DIR="$HOME/.nvm" 41 | install_nvm() { 42 | git clone https://github.com/creationix/nvm "$NVM_DIR" 43 | git -C "$NVM_DIR" checkout $(git -C "$NVM_DIR" describe --abbrev=0 --tags --match "v[0-9]*" origin) 44 | . "$NVM_DIR/nvm.sh" 45 | } 46 | [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" 47 | 48 | 49 | - name: Setup npm to use home directory 50 | copy: 51 | dest: /etc/profile.d/npm.sh 52 | content: | 53 | export PATH="$HOME/.npm-packages/bin:$PATH" # man 1 sh 54 | export NODE_PATH="$HOME/.npm-packages/lib/node_modules" # man 1 node 55 | export NPM_CONFIG_PREFIX="$HOME/.npm-packages" # man 7 npm-config 56 | export N_PREFIX="$HOME/.npm-packages" # installs under ~/.npm-packages/n 57 | 58 | install_node_version() { 59 | mv "$HOME/.npm-packages" "$HOME/.npm-packages-$(node -v)" 60 | echo "The previous versions of your NPM packages have moved. They are now" 61 | echo "accessible at: $HOME/.npm-packages-$(node -v)" 62 | command npm install -g npm 63 | command npm install -g n 64 | n "$1" 65 | command npm install -g yarn 66 | } 67 | 68 | npm() { 69 | echo "Use yarn instead!" >&2 70 | if ! command -v yarn >/dev/null; then 71 | echo 'Run `install_node_version latest` to update Node and install Yarn' >&2 72 | echo 'You can also specify an alias, such as `lts`, `latest`, etc.' >&2 73 | fi 74 | return 1 75 | } 76 | 77 | - name: Setup luarocks versions to use home directory 78 | copy: 79 | dest: /etc/profile.d/luarocks_aliases.sh 80 | content: | 81 | #!/bin/sh 82 | alias luarocks-5.1="lua5.1 /usr/bin/luarocks --local" 83 | alias luarocks-5.2="lua5.2 /usr/bin/luarocks --local" 84 | alias luarocks-5.3="lua5.3 /usr/bin/luarocks --local" 85 | # Need to do 5.1 last, as it adds to LUA_PATH, which would be picked up by the other commands 86 | eval `lua5.3 /usr/bin/luarocks path` 87 | eval `lua5.2 /usr/bin/luarocks path` 88 | eval `lua5.1 /usr/bin/luarocks path` 89 | 90 | 91 | 92 | - name: Set umask 077 in default profile 93 | lineinfile: 94 | path: /etc/profile 95 | line: "umask 077" 96 | 97 | - name: Remove default /etc/skel directory 98 | block: 99 | - file: path=/etc/skel/.profile state=absent 100 | - file: path=/etc/skel/.bash_logout state=absent 101 | - file: path=/etc/skel/.bashrc state=absent 102 | - file: path=/etc/skel/.kshrc state=absent 103 | - file: path=/etc/skel/.mkshrc state=absent 104 | 105 | - name: Provision dotfiles for new accounts from git 106 | copy: 107 | dest: /etc/profile.d/dotfiles.sh 108 | content: | 109 | # check if the dotfiles must be recreated 110 | # Check both ~/.dotfiles and ~/.bash_profile as we 111 | # don't want to run if the user has “old style” dotfiles. 112 | if [ -d ~/.dotfiles ] || [ -f ~/.bash_profile ]; then 113 | return 114 | fi 115 | 116 | # Prepare GnuPG homedir 117 | export GNUPGHOME=$(mktemp -d --tmpdir gpg.XXXXXX) 118 | trap "rm -rf -- '${GNUPGHOME}'; unset GNUPGHOME" EXIT 119 | cat > "${GNUPGHOME}/gpg.conf" <&2 <&2 137 | rm -rf ~/.dotfiles 138 | return 139 | fi 140 | rm -rf -- "${GNUPGHOME}" 141 | unset GNUPGHOME 142 | trap - EXIT 143 | 144 | # stowing 145 | cd ~/.dotfiles 146 | stow bash git gnupg hashbang ssh tmux weechat zsh 147 | cd 148 | 149 | # Make sure a proper maildir is in place 150 | mkdir -p ~/Mail/cur ~/Mail/new ~/Mail/tmp 151 | 152 | # Edit the welcome message 153 | sed -i "s/{date}/$(date '+%a, %-d %b %Y %T %Z')/g" Mail/new/msg.welcome 154 | sed -i "s/{username}/$(whoami)/g" Mail/new/msg.welcome 155 | 156 | - name: Default shell for new users to bash 157 | lineinfile: 158 | path: /etc/default/useradd 159 | regexp: "SHELL=" 160 | line: "SHELL=/bin/bash" 161 | 162 | - name: Default Mail location in homedir 163 | lineinfile: 164 | path: /etc/environment 165 | line: "MAIL=~/Mail" 166 | 167 | - name: Set Gem installs to homedirs 168 | lineinfile: 169 | create: true 170 | path: /etc/gemrc 171 | line: "gem: --user-install --bindir ~/.gem/bin" 172 | 173 | - name: Set NPM installs to homedirs 174 | lineinfile: 175 | create: true 176 | path: /etc/npmrc 177 | line: "prefix = ${HOME}/.npm-packages" 178 | 179 | - name: Setup umask/profile for zsh 180 | copy: 181 | dest: /etc/zsh/zprofile 182 | content: | 183 | umask 077 184 | emulate sh -c 'source /etc/profile' 185 | 186 | - name: Setup luarocks config for various versions 187 | block: 188 | - name: Install Luarocks config for lua 5.1 189 | copy: 190 | dest: /etc/luarocks/config-5.1.lua 191 | content: | 192 | variables = { 193 | LUA_INTERPRETER = "/usr/bin/lua5.1"; 194 | LUA_INCDIR = "/usr/include/lua5.1"; 195 | } 196 | rocks_subdir = "/lib/luarocks/rocks-5.1" 197 | - name: Install Luarocks config for lua 5.2 198 | copy: 199 | dest: /etc/luarocks/config-5.2.lua 200 | content: | 201 | export_lua_path = "export LUA_PATH_5_2='%s'"; 202 | export_lua_cpath = "export LUA_CPATH_5_2='%s'"; 203 | variables = { 204 | LUA_INTERPRETER = "/usr/bin/lua5.2"; 205 | LUA_INCDIR = "/usr/include/lua5.2"; 206 | } 207 | rocks_subdir = "/lib/luarocks/rocks-5.2" 208 | - name: Install Luarocks config for lua 5.3 209 | copy: 210 | dest: /etc/luarocks/config-5.3.lua 211 | content: | 212 | export_lua_path = "export LUA_PATH_5_3='%s'"; 213 | export_lua_cpath = "export LUA_CPATH_5_3='%s'"; 214 | variables = { 215 | LUA_INTERPRETER = "/usr/bin/lua5.3"; 216 | LUA_INCDIR = "/usr/include/lua5.3"; 217 | } 218 | rocks_subdir = "/lib/luarocks/rocks-5.3" 219 | -------------------------------------------------------------------------------- /ansible/tasks/prometheus/main.yml: -------------------------------------------------------------------------------- 1 | - name: Configure prometheus-node-exporter to run on a specific port 2 | copy: 3 | dest: /etc/default/prometheus-node-exporter 4 | content: | 5 | ARGS="--web.listen-address=localhost:9100" 6 | 7 | - name: Install prometheus-node-exporter 8 | apt: 9 | name: 10 | - prometheus-node-exporter 11 | -------------------------------------------------------------------------------- /ansible/tasks/security/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Disable Debian-provided systemd PAM configuration 3 | command: "pam-auth-update --package --remove systemd --force" 4 | 5 | - name: Add hard-required pam_systemd in common-session-noninteractive 6 | copy: 7 | dest: /usr/share/pam-configs/systemd-hashbang 8 | content: | 9 | Name: Register user sessions in systemd hierarchy (Hashbang edition) 10 | Default: yes 11 | Priority: 0 12 | Session-Interactive-Only: no 13 | Session-Type: Additional 14 | Session: 15 | required pam_systemd.so 16 | 17 | - name: Enable custom systemd PAM configuration 18 | command: "pam-auth-update --package --enable systemd-hashbang" 19 | 20 | - name: Configure pam_limits(8) 21 | copy: 22 | dest: /etc/security/limits.conf 23 | content: | 24 | 1000:4294967294 soft nproc 150 25 | 1000:4294967294 hard nproc 200 26 | 1000:4294967294 soft nofile 4096 27 | 1000:4294967294 hard nofile 10240 28 | 29 | - name: "Per-user resource limits: Configure systemd resource accounting" 30 | blockinfile: 31 | path: /etc/systemd/system.conf 32 | marker: "# {mark} ANSIBLE - Config for better resource accounting" 33 | block: | 34 | DefaultCPUAccounting=yes 35 | DefaultBlockIOAccounting=yes 36 | DefaultMemoryAccounting=yes 37 | 38 | - name: "Per-user resource limits: Install script for setting limits" 39 | copy: 40 | dest: /etc/security/limits.sh 41 | mode: "a+x" 42 | content: | 43 | #!/bin/sh -e 44 | 45 | PAM_UID=$(getent passwd "${PAM_USER}" | cut -d: -f3) 46 | 47 | if [ "${PAM_UID}" -ge 1000 ]; then 48 | /bin/systemctl set-property --runtime "user-${PAM_UID}.slice" \ 49 | CPUQuota=50% MemoryLimit=512M BlockIOWeight=10 50 | fi 51 | 52 | - name: "Per-user resource limits: Execute script with pam_exec" 53 | lineinfile: 54 | create: no 55 | path: /etc/pam.d/common-session-noninteractive 56 | insertafter: session\w+required\w+pam_systemd.so 57 | line: "session required pam_exec.so type=open_session /etc/security/limits.sh" 58 | regexp: ^session\w+required\w+pam_exec.so\w+type=open_session\w+/etc/security/limits.sh 59 | 60 | - name: Make sure oidentd can only send proper responses 61 | copy: 62 | dest: /etc/oidentd.conf 63 | content: | 64 | /* 65 | * This is the system-wide configuration file for oidentd. 66 | * This file provides defaults for users. The settings in 67 | * this system-wide file can be overridden by the per-user 68 | * configuration files of users who have been granted 69 | * sufficient capabilities through this file. 70 | * 71 | * See oidentd.conf(5) for more information. 72 | * 73 | * Managed by Ansible 74 | */ 75 | 76 | default { 77 | default { 78 | force numeric 79 | } 80 | } 81 | 82 | - name: Uninstall services with known PAM escapes 83 | apt: 84 | name: 85 | - at 86 | state: absent 87 | 88 | - name: Disable services with known PAM or sandbox escapes 89 | when: not dockerenv.stat.exists 90 | systemd: 91 | name: "{{ item }}" 92 | masked: yes 93 | state: stopped 94 | with_items: 95 | - cron 96 | - glances 97 | 98 | - name: "pam_namespace: Configure systemd-tmpfiles to manage the instances directories" 99 | copy: 100 | dest: /etc/tmpfiles.d/namespaces 101 | content: | 102 | #Type Path Mode UID GID Age Argument 103 | d /tmp/inst 0000 root root - - 104 | d /var/tmp/inst 0000 root root - - 105 | d /run/lock/inst 0000 root root - - 106 | 107 | 108 | - name: "pam_namespace: Configure polyinstantiated directories" 109 | copy: 110 | dest: /etc/security/namespace.conf 111 | content: | 112 | /tmp /tmp/inst/ user root 113 | /var/tmp /var/tmp/inst/ user root 114 | /run/lock /run/lock/inst/ user root 115 | 116 | - name: "pam_namespace: Install the script for setting up polyinstantiated /dev" 117 | copy: 118 | dest: /etc/security/namespace.init 119 | mode: "0755" 120 | content: | 121 | #!/bin/sh -e 122 | # It receives polydir path as $1, the instance path as $2, 123 | # a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3, 124 | # and user name in $4. 125 | 126 | if [ "$1" = "/dev" ]; then 127 | # If we are creating /dev 128 | if [ "$3" = 1 ]; then 129 | # Major and minor number for devices come from 130 | # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devices.txt 131 | mknod -m 666 /dev/null char 1 3 132 | mknod -m 666 /dev/zero char 1 5 133 | mknod -m 666 /dev/full char 1 7 134 | mknod -m 666 /dev/random char 1 8 135 | mknod -m 666 /dev/urandom char 1 9 136 | mknod -m 666 /dev/fuse char 10 229 137 | mknod -m 666 /dev/tty char 5 0 138 | chown root:tty /dev/tty 139 | 140 | # Create devpts mountpoint 141 | mkdir -m 755 /dev/pts 142 | 143 | # Create the shm directory 144 | mkdir -m 1777 /dev/shm 145 | 146 | # Mandatory symlinks 147 | ln -s /proc/self/fd /dev/fd 148 | ln -s fd/0 /dev/stdin 149 | ln -s fd/1 /dev/stdout 150 | ln -s fd/2 /dev/stderr 151 | ln -s null /dev/X0R 152 | 153 | # Recommended symlinks 154 | ln -s /run/systemd/journal/dev-log /dev/log 155 | fi 156 | 157 | mount -o gid=5,mode=0620,ptmxmode=0666 \ 158 | -t devpts devpts /dev/pts 159 | ln -sf pts/ptmx /dev/ptmx 160 | fi 161 | 162 | exit 0 163 | 164 | - name: "Per-user resource limits: Execute script with pam_exec" 165 | lineinfile: 166 | create: no 167 | path: /etc/pam.d/common-session-noninteractive 168 | insertafter: session\w+required\w+pam_env.so 169 | line: "session required pam_namespace.so unmnt_remnt" 170 | regexp: ^session\w+required\w+pam_namespace.so 171 | 172 | - name: Update default umask to 027 173 | lineinfile: 174 | path: /etc/login.defs 175 | regexp: "^UMASK" 176 | line: "UMASK 027" 177 | 178 | - name: Default logrotate wtmp to 0660 179 | lineinfile: 180 | path: /etc/logrotate.conf 181 | regexp: "create .+ root utmp" 182 | line: "create 0660 root utmp" 183 | 184 | - name: Ferm firewall policy 185 | copy: 186 | dest: /etc/ferm/ferm.conf 187 | content: | 188 | table filter { 189 | chain INPUT { 190 | policy ACCEPT; 191 | mod state state INVALID DROP; 192 | } 193 | chain OUTPUT { 194 | policy ACCEPT; 195 | 196 | # connection tracking 197 | mod state state INVALID DROP; 198 | 199 | # Feathercoin mining pool 200 | daddr (176.31.126.191 188.165.223.132) REJECT; 201 | 202 | # bitcoinshell.mooo.com 203 | daddr (92.222.41.125) REJECT; 204 | 205 | # Bitcoin-related protocols 206 | proto (udp tcp) dport (8082 8332 8333 50002) REJECT; 207 | 208 | # Block outgoing traffic to RFC1918/RFC6598 NAT IP ranges 209 | mod iprange dst-range 10.0.0.0-10.255.255.255 REJECT; 210 | mod iprange dst-range 172.16.0.0-172.31.255.255 REJECT; 211 | mod iprange dst-range 192.168.0.1-192.168.255.255 REJECT; 212 | mod iprange dst-range 100.64.0.0-100.127.255.255 REJECT; 213 | 214 | } 215 | } 216 | 217 | - name: Enable Ferm firewall 218 | lineinfile: 219 | line: "ENABLED=\"yes\"" 220 | regexp: ^ENABLED 221 | path: /etc/default/ferm 222 | 223 | - name: Filesystem security settings 224 | blockinfile: 225 | path: /etc/fstab 226 | marker: "# {mark} ANSIBLE - Filesystem Security Settings" 227 | block: | 228 | proc /proc proc defaults,hidepid=2 0 0 229 | udev /dev devtmpfs defaults,nosuid,noatime 0 0 230 | devpts /dev/pts devpts defaults,newinstance,ptmxmode=0666 0 0 231 | 232 | - name: "Restrict access to kernel symbols" 233 | copy: 234 | dest: /etc/tmpfiles.d/kallsyms 235 | content: | 236 | #Type Path Mode UID GID Age Argument 237 | z /proc/kallsyms 400 - - - 238 | 239 | - name: "sudo: Change the default configuration" 240 | blockinfile: 241 | path: /etc/sudoers 242 | marker: "# {mark} ANSIBLE - PTY configuration for users" 243 | block: | 244 | Defaults !requiretty, !tty_tickets 245 | Defaults use_pty 246 | 247 | - name: Ensure haveged uses 2048 bit watermark 248 | lineinfile: 249 | path: /etc/default/haveged 250 | regexp: "^DAEMON_ARGS=" 251 | line: "DAEMON_ARGS=\"-w 2048\"" 252 | 253 | - name: Prevent user access to some sensitive files 254 | block: 255 | - file: 256 | mode: 0660 257 | path: '{{ item }}' 258 | with_items: 259 | - /var/run/utmp 260 | - /var/log/wtmp 261 | - /var/log/lastlog 262 | - acl: 263 | path: '{{ item }}' 264 | entry: 'group:adm:r' 265 | state: present 266 | with_items: 267 | - /var/run/utmp 268 | - /var/log/wtmp 269 | - /var/log/lastlog 270 | 271 | - name: "sysctl: Restrict potentially sensitive kernel dmesg output" 272 | lineinfile: 273 | create: true 274 | path: /etc/sysctl.d/10-dmsg.conf 275 | line: "kernel.dmesg_restrict = 1" 276 | 277 | - name: "sysctl: Edit sysctl.conf" 278 | lineinfile: 279 | path: /etc/sysctl.conf 280 | line: "{{ item.key }} = {{ item.value }}" 281 | regexp: ^#?{{ item.key }}\w*= 282 | with_dict: 283 | # spoof protection via reverse-path filter 284 | net.ipv4.conf.default.rp_filter: 1 285 | net.ipv4.conf.all.rp_filter: 1 286 | 287 | # Enable arp notifications for eth0 288 | net.ipv4.conf.eth0.arp_notify: 1 289 | 290 | # Adjust VM Swappiness to more sane default 291 | vm.swappiness: 60 292 | 293 | # Use Controlled Delay to avoid bufferbloat 294 | net.core.default_qdisc: fq_codel 295 | 296 | # Deny use of perf_event_open to unprivileged processes 297 | kernel.perf_event_paranoid: 2 298 | 299 | 300 | - name: "ssh: Don't allow Roaming for ssh clients" 301 | lineinfile: 302 | path: /etc/ssh/ssh_config 303 | line: "UseRoaming no" 304 | 305 | - name: "ssh: Don't use dsa keys in sshd_config" 306 | lineinfile: 307 | path: /etc/ssh/sshd_config 308 | line: "HostKey /etc/ssh/ssh_host_dsa_key" 309 | state: absent 310 | 311 | - name: "ssh: Set global sshd_config settings" 312 | lineinfile: 313 | path: /etc/ssh/sshd_config 314 | line: "{{ item.key }} {{ item.value }}" 315 | regexp: "^#?{{ item.key }} " 316 | with_dict: 317 | # Use ssh privilege separation sandboxing 318 | UsePrivilegeSeparation: sandbox 319 | 320 | # Disable password authentication 321 | PasswordAuthentication: "no" 322 | 323 | # Allow use of client-specified gateway ports 324 | GatewayPorts: clientspecified 325 | 326 | - name: "ssh: Allow root ssh via hardcoded keys as failsafe" 327 | blockinfile: 328 | path: /etc/ssh/sshd_config 329 | marker: "# {mark} ANSIBLE - Root SSH via hardcoded keys" 330 | block: | 331 | Match User root 332 | AuthorizedKeysFile .ssh/authorized_keys 333 | AuthorizedKeysCommand /bin/true 334 | Match all 335 | -------------------------------------------------------------------------------- /ansible/tasks/tor/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # TODO YELL AT -FUCKING EVERYONE- FOR NOT ALLOWING NO UID PGP KEYS 3 | # IT HAS BROKEN FUCKING EVERYTHING 4 | # THANK U FOR COMING TO MY TED TALK 5 | - apt_key: 6 | data: "{{ lookup('file', 'apt/tor.asc') }}" 7 | id: A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 8 | keyring: /etc/apt/trusted.gpg.d/deb.torproject.org-keyring.gpg 9 | 10 | - apt_repository: 11 | repo: deb https://deb.torproject.org/torproject.org {{ ansible_distribution_release }} main 12 | state: present 13 | filename: tor 14 | 15 | - name: Install tor packages 16 | apt: 17 | name: 18 | - deb.torproject.org-keyring 19 | - python-torctl 20 | - tor 21 | - torsocks 22 | - tor-arm 23 | 24 | - name: setup torsocks to accept inbound connections 25 | lineinfile: 26 | path: /etc/tor/torsocks.conf 27 | line: "AllowInbound 1" 28 | 29 | - name: enable tor service 30 | systemd: 31 | name: tor 32 | enabled: yes 33 | masked: no 34 | state: started 35 | when: not dockerenv.stat.exists 36 | -------------------------------------------------------------------------------- /ansible/tasks/userdb/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install required packages for userdb auth 3 | apt: 4 | name: 5 | - libnss-pgsql2 6 | - libpam-ssh-agent-auth 7 | - postgresql-client 8 | 9 | - name: Ensure sssd is not installed 10 | apt: 11 | name: "{{ item }}" 12 | state: absent 13 | with_items: 14 | - sssd 15 | - libpam-sss 16 | 17 | - name: Add userdb-keys-command user 18 | user: 19 | name: userdb-keys-command 20 | system: yes 21 | 22 | - name: Install userdb authorized-keys 23 | block: 24 | - file: 25 | path: "/{{ item.path }}" 26 | state: directory 27 | mode: "0755" 28 | with_filetree: "tasks/userdb/templates" 29 | when: item.state == 'directory' 30 | - template: 31 | src: "{{ item.src }}" 32 | dest: "/{{ item.path | regex_replace('.j2','') }}" 33 | mode: "{{ item.mode[1] == '7' and '0755' or '0644' }}" 34 | with_filetree: "tasks/userdb/templates" 35 | when: item.state == 'file' 36 | 37 | - name: Configure ssh to use userdb for authorized-keys 38 | blockinfile: 39 | path: /etc/ssh/sshd_config 40 | marker: "# {mark} ANSIBLE - userdb config for ssh" 41 | block: | 42 | AuthorizedKeysFile none 43 | AuthorizedKeysCommand /usr/local/bin/authorized-keys %u 44 | AuthorizedKeysCommandUser userdb-keys-command 45 | 46 | - name: Update nsswitch to use pgsql for passwd 47 | lineinfile: 48 | path: /etc/nsswitch.conf 49 | regexp: "^passwd:" 50 | line: "passwd: files pgsql" 51 | 52 | - name: Update nsswitch to use pgsql for group 53 | lineinfile: 54 | path: /etc/nsswitch.conf 55 | regexp: "^group:" 56 | line: "group: files pgsql" 57 | 58 | - name: Update nsswitch to use pgsql for shadow 59 | lineinfile: 60 | path: /etc/nsswitch.conf 61 | regexp: "^shadow:" 62 | line: "shadow: files pgsql" 63 | 64 | - name: Use libpam-ssh-agent-auth for sudo 65 | apt: 66 | name: 67 | - sudo 68 | 69 | - name: Configure sudo to use userdb-keys-command 70 | copy: 71 | dest: /etc/pam.d/sudo 72 | content: | 73 | #%PAM-1.0 74 | 75 | auth sufficient pam_ssh_agent_auth.so authorized_keys_command=/usr/local/bin/authorized-keys authorized_keys_user=userdb-keys-command 76 | @include common-auth 77 | @include common-account 78 | @include common-session-noninteractive 79 | 80 | - name: Keep SSH_AUTH_SOCK for sudo sessions 81 | blockinfile: 82 | path: /etc/sudoers 83 | marker: "# {mark} ANSIBLE - keep SSH_AUTH_SOCK for sudo sessions" 84 | insertbefore: "Defaults\\s+env_reset" 85 | block: | 86 | Defaults env_keep += "SSH_AUTH_SOCK" 87 | 88 | - name: Configure libnss-pgsql2 89 | block: 90 | - copy: 91 | dest: /etc/nss-pgsql.conf 92 | # these db credentials have read-only permissions 93 | content: | 94 | connectionstring = {{ userdb_connectionstring }} 95 | 96 | # Must return "usernames", 1 column, list 97 | getgroupmembersbygid = select name from passwd where uid=$1 union select name from passwd inner join aux_groups on(passwd.uid=aux_groups.uid and aux_groups.gid=$1) 98 | # Must return passwd_name, passwd_passwd, passwd_gecos, passwd_dir, passwd_shell, passwd_uid, passwd_gid 99 | getpwnam = select name, 'x', data->>'gecos', '/home/' || name, shell, uid, uid from passwd where name = $1 100 | # Must return passwd_name, passwd_passwd, passwd_gecos, passwd_dir, passwd_shell, passwd_uid, passwd_gid 101 | getpwuid = select name, 'x', data->>'gecos', '/home/' || name, shell, uid, uid from passwd where uid = $1 102 | # All users 103 | allusers = select name, 'x', data->>'gecos', '/home/' || name, shell, uid, uid from passwd 104 | # Must return group_name, group_passwd, group_gid 105 | getgrnam = select passwd.name, 'x', passwd.uid, ARRAY[passwd.name] from passwd where passwd.name=$1 union select name, 'x', gid, ARRAY(select passwd.name from passwd inner join aux_groups on(passwd.uid=aux_groups.uid and aux_groups.gid = "group".gid)) as members from "group" where name = $1 106 | # Must return group_name, group_passwd, group_gid 107 | getgrgid = select passwd.name, 'x', passwd.uid, ARRAY[passwd.name] from passwd where passwd.uid=$1 union select name, 'x', gid, ARRAY(select passwd.name from passwd inner join aux_groups on(passwd.uid=aux_groups.uid and aux_groups.gid = "group".gid)) as members from "group" where gid = $1 108 | # Must return gid. %s MUST appear first for username match in where clause 109 | groups_dyn = select gid from aux_groups inner join passwd on(aux_groups.uid = passwd.uid) where passwd.name = $1 and aux_groups.gid <> $2 110 | 111 | allgroups = select name, 'x', gid, ARRAY(select passwd.name from passwd inner join aux_groups on (passwd.uid = aux_groups.uid) inner join "group" on(aux_groups.gid = "group".gid)) from "group" union select name, 'x', uid, ARRAY[passwd.name] as members from passwd 112 | 113 | # A query returning shadow_name, shadow_passwd, shadow_lstchg, shadow_min, shadow_max, shadow_warn, shadow_inact, shadow_expire, shadow_flag for a given username 114 | shadowbyname = select name, 'x', 18245, '', '', '', '', '', '' from passwd where name = $1 115 | 116 | # A query returning shadow_name, shadow_passwd, shadow_lstchg, shadow_min, shadow_max, shadow_warn, shadow_inact, shadow_expire, shadow_flag for all users 117 | shadow = select name, 'x', 18245, '', '', '', '', '', '' from passwd 118 | register: nss_pgsql_copy 119 | 120 | - copy: 121 | dest: /etc/nss-pgsql-root.conf 122 | content: | 123 | shadowconnectionstring = {{ userdb_connectionstring }} 124 | 125 | # # A query returning shadow_name, shadow_passwd, shadow_lstchg, shadow_min, shadow_max, shadow_warn, shadow_inact, shadow_expire, shadow_flag for a given username 126 | shadowbyname = select name, '!', 18086, 0, 99999, '', '', '99999', '' from passwd where name = $1 127 | # 128 | # # A query returning shadow_name, shadow_passwd, shadow_lstchg, shadow_min, shadow_max, shadow_warn, shadow_inact, shadow_expire, shadow_flag for all users 129 | shadow = select name, '!', 18086, 0, 99999, '', '99999', '' from passwd 130 | register: nss_pgsql_root_copy 131 | 132 | - systemd: 133 | name: nscd 134 | state: restarted 135 | when: (nss_pgsql_copy.changed or nss_pgsql_root_copy.changed) and not dockerenv.stat.exists 136 | -------------------------------------------------------------------------------- /ansible/tasks/userdb/templates/usr/local/bin/authorized-keys.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | user="$(id -u "$1")" 4 | curl -s "{{ userdb_apidomain }}/v1/ssh_public_key?uid=eq.$user&select=type,key" \ 5 | | jq -r 'map(.type + " " + .key) | .[]' 6 | 7 | -------------------------------------------------------------------------------- /config.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "aws_access_key": "foo", 3 | "aws_secret_key": "bar", 4 | "docker_user": "username", 5 | "docker_pass": "password", 6 | "atlas_token": "token", 7 | "bintray_user": "username", 8 | "bintray_key": "api_key" 9 | } 10 | -------------------------------------------------------------------------------- /packer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "disk_size": "100000", 4 | "memory": "4G", 5 | "cpus": "2", 6 | "headless": "true", 7 | "iso_url": "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.3.0-amd64-netinst.iso", 8 | "iso_checksum": "6a901b5abe43d88b39d627e1339d15507cc38f980036b928f835e0f0e957d3d8", 9 | "release": "buster", 10 | "version": "{{ env `VERSION`}}", 11 | "extra_arguments": "{{ env `ANSIBLE_ARGS` }}" 12 | }, 13 | "builders": [ 14 | { 15 | "type": "lxc", 16 | "name": "lxc", 17 | "config_file": "/usr/share/lxc/config/common.conf", 18 | "template_name": "download", 19 | "template_parameters": [ 20 | "--dist", "debian", 21 | "--release", "{{ user `release` }}", 22 | "--arch", "amd64", 23 | "--keyserver", "hkp://p80.pool.sks-keyservers.net:80" 24 | ], 25 | "target_runlevel": 3 26 | }, 27 | { 28 | "name": "qemu", 29 | "type": "qemu", 30 | "format": "qcow2", 31 | "headless": "{{ user `headless` }}", 32 | "accelerator": "kvm", 33 | "disk_interface": "virtio-scsi", 34 | "disk_size": "{{ user `disk_size` }}", 35 | "iso_url": "{{ user `iso_url` }}", 36 | "iso_checksum": "{{ user `iso_checksum` }}", 37 | "iso_checksum_type": "sha256", 38 | "http_directory": "packer/http", 39 | "ssh_username": "root", 40 | "ssh_password": "shell", 41 | "shutdown_command": "shutdown -h now", 42 | "ssh_wait_timeout": "120m", 43 | "boot_wait": "2s", 44 | "boot_command": [ 45 | "", 46 | "install ", 47 | "auto=true ", 48 | "priority=critical ", 49 | "interface=auto ", 50 | "url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 51 | "" 52 | ], 53 | "qemuargs": [ 54 | [ "-m", "{{ user `memory` }}" ], 55 | [ "-smp", "cpus={{ user `cpus`}}"] 56 | ], 57 | "output_directory": ".packer/build/qemu/" 58 | }, 59 | { 60 | "name": "virtualbox", 61 | "type": "virtualbox-iso", 62 | "format": "ova", 63 | "headless": "{{ user `headless` }}", 64 | "disk_size": "{{ user `disk_size` }}", 65 | "guest_os_type": "Debian_64", 66 | "iso_url": "{{ user `iso_url` }}", 67 | "iso_checksum": "{{ user `iso_checksum` }}", 68 | "iso_checksum_type": "sha256", 69 | "http_directory": "packer/http", 70 | "ssh_username": "root", 71 | "ssh_password": "shell", 72 | "shutdown_command": "shutdown -h now", 73 | "ssh_wait_timeout": "60m", 74 | "boot_wait": "5s", 75 | "boot_command": [ 76 | "", 77 | "install ", 78 | "auto=true ", 79 | "priority=critical ", 80 | "interface=auto ", 81 | "url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 82 | "" 83 | ], 84 | "output_directory": ".packer/build/virtualbox/" 85 | }, 86 | { 87 | "name": "docker", 88 | "type": "docker", 89 | "image": "debian:{{ user `release` }}", 90 | "changes": [ 91 | "ENV container=docker", 92 | "VOLUME ['/sys/fs/cgroup','/run','/run/lock','/tmp']", 93 | "EXPOSE 20 80 443", 94 | "STOPSIGNAL SIGRTMIN+3", 95 | "CMD ['/lib/systemd/systemd']" 96 | ], 97 | "volumes": { 98 | "/sys/fs/cgroup":"/sys/fs/cgroup:ro" 99 | }, 100 | "run_command": [ 101 | "-dit", 102 | "-e", "container=docker" , 103 | "--security-opt", "seccomp=unconfined", 104 | "{{.Image}}", 105 | "/bin/bash" 106 | ], 107 | "export_path": ".packer/build/docker/docker.tar" 108 | } 109 | ], 110 | "provisioners": [ 111 | { 112 | "type": "ansible", 113 | "extra_arguments": "{{ user `extra_arguments`}}", 114 | "playbook_file": "ansible/main.yml" 115 | } 116 | ], 117 | "post-processors": [[ 118 | { 119 | "type": "compress", 120 | "output": "dist/docker-{{ user `version` }}.tar.gz", 121 | "format": "gz", 122 | "only": ["docker"] 123 | }, 124 | { 125 | "type": "shell-local", 126 | "inline": [ 127 | "cd dist/", 128 | "ln -s docker-{{ user `version` }}.tar.gz docker-latest.tar.gz" 129 | ], 130 | "only": ["docker"] 131 | }, 132 | { 133 | "type": "shell-local", 134 | "inline": [ 135 | "cp .packer/build/qemu/packer-qemu dist/qemu-{{ user `version` }}.qcow2", 136 | "ln -s qemu-{{ user `version` }}.qcow2 dist/qemu-latest.qcow2" 137 | ], 138 | "only": ["qemu"] 139 | }, 140 | { 141 | "type": "vagrant", 142 | "keep_input_artifact": true, 143 | "output": "dist/vagrant-{{ user `version` }}.box", 144 | "only": ["virtualbox"] 145 | }, 146 | { 147 | "type": "shell-local", 148 | "inline": [ 149 | "cp .packer/build/virtualbox/*.ova dist/virtualbox-{{ user `version` }}.ova", 150 | "ln -s virtualbox-{{ user `version` }}.ova dist/docker-latest.ova", 151 | "ln -s vagrant-{{ user `version` }}.box dist/vagrant-latest.box" 152 | ], 153 | "only": ["virtualbox"] 154 | } 155 | ]] 156 | } 157 | -------------------------------------------------------------------------------- /packer/http/preseed.cfg: -------------------------------------------------------------------------------- 1 | d-i passwd/root-login boolean true 2 | d-i passwd/make-user boolean false 3 | d-i passwd/root-password password shell 4 | d-i passwd/root-password-again password shell 5 | d-i user-setup/allow-password-weak boolean true 6 | 7 | d-i debian-installer/locale string en_US 8 | d-i keyboard-configuration/xkb-keymap select us 9 | d-i netcfg/choose_interface select auto 10 | d-i mirror/protocol string http 11 | d-i mirror/country string manual 12 | d-i mirror/http/hostname string deb.debian.org 13 | d-i mirror/http/directory string /debian 14 | d-i clock-setup/utc boolean true 15 | d-i time/zone string Etc/UTC 16 | d-i clock-setup/ntp boolean true 17 | d-i partman-auto/method string regular 18 | d-i partman-auto/choose_recipe select atomic 19 | d-i partman-partitioning/confirm_write_new_label boolean true 20 | d-i partman/choose_partition select finish 21 | d-i partman/confirm boolean true 22 | d-i partman/confirm_nooverwrite boolean true 23 | tasksel tasksel/first multiselect ssh-server 24 | d-i pkgsel/upgrade select full-upgrade 25 | popularity-contest popularity-contest/participate boolean false 26 | d-i grub-installer/only_debian boolean true 27 | d-i grub-installer/with_other_os boolean true 28 | d-i grub-installer/bootdev string default 29 | d-i finish-install/reboot_in_progress note 30 | d-i preseed/late_command string \ 31 | sed -i -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /target/etc/ssh/sshd_config; \ 32 | sed -i -e 's/^#\?PermitRootLogin.*/PermitRootLogin yes/g' /target/etc/ssh/sshd_config; \ 33 | if [ -x "/target/sbin/rdnssd" -a ! -x "/target/sbin/resolvconf" ] ; then \ 34 | in-target systemctl disable rdnssd.service ; \ 35 | fi 36 | 37 | -------------------------------------------------------------------------------- /packer/publish.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "disk_size": "100000", 4 | "headless": "true", 5 | "atlas_token": "{{ env `ATLAS_TOKEN` }}", 6 | "docker_user": "{{ env `DOCKER_USER` }}", 7 | "docker_pass": "{{ env `DOCKER_PASS` }}", 8 | "version": "{{ env `ATLAS_TOKEN` }}", 9 | "iso_url": "https://cdimage.debian.org/debian-cd/8.7.1/amd64/iso-cd/debian-8.7.1-amd64-netinst.iso", 10 | "iso_checksum": "749a15b7690769dd99e85d6104182a03d370b04b36106ec7cfaf6a551aa89fb4" 11 | }, 12 | "builders": [ 13 | { 14 | "name": "qemu", 15 | "type": "qemu", 16 | "format": "qcow2", 17 | "headless": "{{ user `headless` }}", 18 | "accelerator": "kvm", 19 | "disk_interface": "virtio-scsi", 20 | "disk_size": "{{ user `disk_size` }}", 21 | "iso_url": "{{ user `iso_url` }}", 22 | "iso_checksum": "{{ user `iso_checksum` }}", 23 | "iso_checksum_type": "sha256", 24 | "http_directory": "http", 25 | "ssh_username": "root", 26 | "ssh_password": "shell", 27 | "shutdown_command": "shutdown -h now", 28 | "ssh_wait_timeout": "60m", 29 | "boot_wait": "2s", 30 | "boot_command": [ 31 | "", 32 | "install ", 33 | "auto=true ", 34 | "priority=critical ", 35 | "interface=auto ", 36 | "url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 37 | "" 38 | ], 39 | "output_directory": "dist" 40 | }, 41 | { 42 | "name": "vagrant", 43 | "type": "virtualbox-iso", 44 | "headless": "{{ user `headless` }}", 45 | "disk_size": "{{ user `disk_size` }}", 46 | "guest_os_type": "Debian_64", 47 | "iso_url": "{{ user `iso_url` }}", 48 | "iso_checksum": "{{ user `iso_checksum` }}", 49 | "iso_checksum_type": "sha256", 50 | "http_directory": "http", 51 | "ssh_username": "root", 52 | "ssh_password": "shell", 53 | "shutdown_command": "shutdown -h now", 54 | "ssh_wait_timeout": "60m", 55 | "boot_wait": "2s", 56 | "boot_command": [ 57 | "", 58 | "install ", 59 | "auto=true ", 60 | "priority=critical ", 61 | "interface=auto ", 62 | "url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 63 | "" 64 | ], 65 | "output_directory": "dist" 66 | }, 67 | { 68 | "name": "docker", 69 | "type": "docker", 70 | "image": "debian:jessie", 71 | "commit": "true", 72 | "changes": [ 73 | "ENV container=docker", 74 | "VOLUME ['/sys/fs/cgroup','/run','/run/lock','/tmp']", 75 | "EXPOSE 20 80 443", 76 | "ENTRYPOINT /sbin/init" 77 | ] 78 | } 79 | ], 80 | "post-processors": [[ 81 | { 82 | "type": "docker-tag", 83 | "only": ["docker"], 84 | "repository": "hashbang/shell-server", 85 | "tag": "latest" 86 | }, 87 | { 88 | "type": "docker-tag", 89 | "only": ["docker"], 90 | "repository": "hashbang/shell-server", 91 | "tag": "{{user `version`}}" 92 | }, 93 | { 94 | "type": "docker-save", 95 | "only": ["docker"], 96 | "path": "dist/docker.tar" 97 | }, 98 | { 99 | "type": "docker-push", 100 | "only": ["docker"] 101 | }, 102 | { 103 | "type": "vagrant", 104 | "only": ["vagrant"], 105 | "output": "dist/{{.BuildName}}_{{.Provider}}.box" 106 | }, 107 | { 108 | "type": "vagrant-cloud", 109 | "only": ["vagrant"], 110 | "box_tag": "hashbang/shell-server", 111 | "access_token": "{{user `atlas_token`}}", 112 | "version": "{{user `version`}}" 113 | } 114 | ]], 115 | "provisioners": [ 116 | { 117 | "type": "shell", 118 | "script": "setup.sh" 119 | } 120 | ] 121 | } 122 | --------------------------------------------------------------------------------