AWSTemplateFormatVersion: '2010-09-09' Description: Creates a single EC2 instance with a pruned Bitcoin Core node, C-Lightning, Lightning Charge, Postgres, Ruby on Rails and Matreon. Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Server Parameters: - KeyName - BugsEmail - Label: default: Bitcoin Parameters: - Network - Label: default: Matreon Parameters: - Prefix - Domain - FromEmail - SmtpHost - SmtpUser - SmtpPassword - SmtpPort - Label: default: Podcast Parameters: - Podcast - PodcastTitle - PodcastImage - PodcastUrl - Label: default: Developer Parameters: - Repository - Branch Parameters: KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instances Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: must be the name of an existing EC2 KeyPair. Network: Description: Real Bitcoin or testnet Type: String Default: testnet AllowedValues: - testnet - bitcoin Prefix: Type: String Description: For https:// we'll automatically request a certificate. You agree to the ACME server's Subscriber Agreement. Default: 'https' AllowedValues: - 'https' - 'http' Domain: Default: example.com Description: Domain without http(s), no trailing slash Type: String MinLength: '5' MaxLength: '100' FromEmail: Default: you@example.com Description: From email address. Also submitted during HTTPS certificate registration. Type: String MinLength: '5' MaxLength: '100' BugsEmail: Default: bugs@example.com Description: Bug report email address Type: String MinLength: '5' MaxLength: '100' SmtpHost: Default: smtp.fastmail.com Description: SMTP server Type: String MinLength: '5' MaxLength: '100' SmtpPort: Default: '587' Description: SMTP port Type: String MinLength: '1' MaxLength: '5' SmtpUser: Default: you@example.com Description: SMTP username Type: String MinLength: '5' MaxLength: '100' SmtpPassword: Default: '' Description: SMTP password Type: String NoEcho: 'true' MinLength: '0' MaxLength: '100' Podcast: Description: Enable podcast feature. Currently requires an existing RSS source. Type: String Default: '0' AllowedValues: - '0' - '1' PodcastTitle: Description: Podcast title Type: String Default: '' MinLength: '0' MaxLength: '100' PodcastImage: Description: Podcast image URL Type: String Default: '' MinLength: '0' MaxLength: '255' PodcastUrl: Description: Existing podcast RSS feed Type: String Default: '' MinLength: '0' MaxLength: '255' GitURL: Description: Git repository URL Type: String MinLength: '0' MaxLength: '255' Default: 'https://github.com/Sjors/matreon.git' GitBranch: Description: Git branch Type: String MinLength: '0' MaxLength: '255' Default: 'master' Conditions: NetworkBitcoin: !Equals [!Ref 'Network', 'bitcoin'] NetworkTestnet: !Equals [!Ref 'Network', 'testnet'] UseDomain: !Not [!Equals [!Ref 'Domain', '']] SSL: !Equals [!Ref 'Prefix', 'https'] Resources: WebServer: Type: AWS::EC2::Instance DependsOn: IPAddress Metadata: AWS::CloudFormation::Init: configSets: full_install: - install_cfn - users_groups - env_files - storage - shared_packages_managers_languages - clone_repo - install_bitcoind - prepare_initial_blockchain_download - install_lightningd - install_lightning_charge - install_postgres - install_rails - install_nginx - install_certbot - prepare_cron_and_services install_cfn: files: /etc/cfn/cfn-hup.conf: content: !Sub | [main] stack=${AWS::StackId} region=${AWS::Region} mode: '000400' owner: root group: root /etc/cfn/hooks.d/cfn-auto-reloader.conf: content: !Sub | [cfn-auto-reloader-hook] triggers=post.update path=Resources.WebServer.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer --configsets full_install --region ${AWS::Region} runas=root mode: '000400' owner: root group: root services: sysvinit: cfn-hup: enabled: 'true' ensureRunning: 'true' files: - /etc/cfn/cfn-hup.conf - /etc/cfn/hooks.d/cfn-auto-reloader.conf users_groups: commands: 01_bitcoin: command: groupadd -r bitcoin && useradd -r -m -g bitcoin bitcoin 02_charge: command: groupadd -r charge && useradd -r -m -g charge charge 03_matreon: command: groupadd -r matreon && useradd -r -m -g matreon matreon 04_certbot: command: groupadd -r certbot && useradd -r -m -g certbot certbot 10_lightningrpc_group: command: groupadd lightningrpc && usermod -a -G lightningrpc bitcoin && usermod -a -G lightningrpc charge env_files: files: /root/.env: content: !Sub | DOMAIN=${Domain} IP=${IPAddress} EMAIL=${FromEmail} /home/matreon/.env: content: !Sub | RAILS_ENV=production NODE_ENV=production DATABASE_URL=postgres://matreon@localhost:5432 HOSTNAME=${Prefix}://${Domain} FROM_EMAIL=${FromEmail} BUGS_TO=${BugsEmail} SMTP_HOST=${SmtpHost} SMTP_PORT=${SmtpPort} SMTP_USERNAME=${SmtpUser} SMTP_PASSWORD=${SmtpPassword} PODCAST=${Podcast} PODCAST_TITLE=${PodcastTitle} PODCAST_URL=${PodcastUrl} PODCAST_IMAGE=${PodcastImage} mode: '000400' owner: matreon group: matreon /home/charge/.env: content: "\n" mode: '000400' owner: charge group: charge commands: 20_generate_lightning_charge_api_token: command: export API_TOKEN=`hexdump -n 64 -e '16/4 "%08x" 1 "\n"' /dev/random` && echo "LIGHTNING_CHARGE_API_TOKEN=$API_TOKEN" >> /home/matreon/.env && echo "API_TOKEN=$API_TOKEN" >> /home/charge/.env storage: commands: 01_format_magnetic_volume: command: mkfs -t ext4 /dev/xvdb 02_mount_magnetic_volume: command: mkdir /mnt/magnetic && echo "/dev/xvdb /mnt/magnetic ext4 defaults,nofail 0 2" >> /etc/fstab && mount -a 10_format_ssd: command: mkfs.ext4 -E nodiscard /dev/nvme0n1 11_mount_ssd: command: mkdir /mnt/ssd && mount -o discard /dev/nvme0n1 /mnt/ssd shared_packages_managers_languages: packages: yum: git: [] jq: [] patch: [] gcc: [] gcc-c++: [] automake: [] libtool: [] gmp-devel: [] sqlite-devel: [] python3: [] net-tools: [] commands: 01_upgrade: command: yum update -y 10_add_npm_repo: command: curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - 11_install_node: command: yum -y install nodejs 12_install_yarn: command: npm install -g yarn 20_install_ruby: command: amazon-linux-extras install ruby2.4 21_install_bundler: command: yum install -y redhat-rpm-config ruby-devel && gem install bundler --no-document clone_repo: commands: 01_clone_repo: command: !Sub git clone ${GitURL} /usr/local/src/matreon && cd /usr/local/src/matreon && git checkout ${GitBranch} install_bitcoind: commands: 01_install: command: sh /usr/local/src/matreon/vendor/bitcoin/install.sh 02_copy_bitcoind_config: command: mkdir /etc/bitcoin && cp /usr/local/src/matreon/vendor/bitcoin/bitcoin.conf /etc/bitcoin/bitcoin.conf && chmod 444 /etc/bitcoin/bitcoin.conf 03_set_bitcoin_network: command: !If - NetworkBitcoin - echo - echo "testnet=1" >> /etc/bitcoin/bitcoin.conf 04_create_datadir: command: mkdir /home/bitcoin/.bitcoin && chown -R bitcoin:bitcoin /home/bitcoin/.bitcoin 05_create_blocks_dir: command: !If - NetworkBitcoin - su - bitcoin --command "mkdir -p ~/.bitcoin/blocks-index" && mkdir /mnt/magnetic/blocks && chown -R bitcoin:bitcoin /mnt/magnetic/blocks && su - bitcoin --command "ln -s /home/bitcoin/.bitcoin/blocks-index /mnt/magnetic/blocks/index" && su - bitcoin --command "ln -s /mnt/magnetic/blocks /home/bitcoin/.bitcoin/blocks" - su - bitcoin --command "mkdir -p ~/.bitcoin/testnet3/blocks-index" && mkdir /mnt/magnetic/blocks-testnet3 && chown -R bitcoin:bitcoin /mnt/magnetic/blocks-testnet3 && su - bitcoin --command "ln -s /home/bitcoin/.bitcoin/testnet3/blocks-index /mnt/magnetic/blocks-testnet3/index" && su - bitcoin --command "ln -s /mnt/magnetic/blocks-testnet3 /home/bitcoin/.bitcoin/testnet3/blocks" prepare_initial_blockchain_download: commands: 01_add_ssd_bitcoin_dir: command: mkdir /mnt/ssd/bitcoin && chown -R bitcoin:bitcoin /mnt/ssd/bitcoin && ln -s /mnt/ssd/bitcoin /home/bitcoin/big-disk && chown -h bitcoin:bitcoin /home/bitcoin/big-disk install_lightningd: packages: yum: zlib-devel: [] commands: 01_clone_repo: command: git clone https://github.com/ElementsProject/lightning /usr/local/src/lightning 02_checkout_release: command: cd /usr/local/src/lightning && git checkout v0.6rc1 03_configure: command: cd /usr/local/src/lightning && ./configure 04_make: command: cd /usr/local/src/lightning && make && make install 10_create_datadir_and_copy_config: command: mkdir /home/bitcoin/.lightning && cp /usr/local/src/matreon/vendor/lightning/config /home/bitcoin/.lightning && chown -R bitcoin:bitcoin /home/bitcoin/.lightning 11_set_lightning_network: command: !If - NetworkBitcoin - echo "network=bitcoin" >> /home/bitcoin/.lightning/config - echo "network=testnet" >> /home/bitcoin/.lightning/config 12_set_lightning_announce_addr: command: !Sub echo "announce-addr=${IPAddress}" >> /home/bitcoin/.lightning/config 13_share_rpc: command: mkdir /etc/lightning && chown bitcoin:lightningrpc /etc/lightning install_lightning_charge: commands: 01_allow_global_npm_packages: command: su - charge --command "mkdir ~/.npm-global && npm config set prefix '~/.npm-global'" && su - charge --command "echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc" 02_clone_repo: command: su - charge --command "git clone https://github.com/Sjors/lightning-charge" && su - charge --command "cd lightning-charge && git checkout 2018/05/node-uri" 03_npm_install: command: su - charge --command "cd lightning-charge && npm link" install_postgres: commands: 01_install_postgress: command: yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-redhat10-10-2.noarch.rpm && sed -i "s/rhel-\$releasever-\$basearch/rhel-latest-x86_64/g" "/etc/yum.repos.d/pgdg-10-redhat.repo" && yum install -y postgresql10-devel postgresql10-server 02_configure_postgres: command: su - postgres --command "/usr/pgsql-10/bin/initdb -D /var/lib/pgsql/10/data" && systemctl enable postgresql-10.service 03_start_postgres: command: systemctl start postgresql-10.service 04_create_db_for_matreon: command: su - postgres --command "createuser matreon && createdb -O matreon matreon" 05_ruby_gem: command: gem install pg --no-document -- --with-pg-config=/usr/pgsql-10/bin/pg_config install_rails: packages: yum: libxml2: [] libxml2-devel: [] libxslt: [] libxslt-devel: [] commands: 01_gems_with_native_extensions: command: gem install nokogiri --no-document 10_clone_repo_again: command: !Sub mkdir -p /var/www/matreon && git clone ${GitURL} /var/www/matreon && cd /var/www/matreon && git checkout ${GitBranch} && chown -R matreon:matreon /var/www/matreon 21_set_secret_key_base: command: echo "SECRET_KEY_BASE=`hexdump -n 64 -e '16/4 \"%08x\" 1 \"\n\"' /dev/random`" >> /home/matreon/.env 22_set_devise_secret_key_key: command: echo "DEVISE_SECRET_KEY=`hexdump -n 64 -e '16/4 \"%08x\" 1 \"\n\"' /dev/random`" >> /home/matreon/.env install_nginx: files: /etc/nginx/conf.d/matreon/server_name: content: !If - UseDomain - !Sub | server_name ${Domain}; - !Sub | server_name _; /etc/nginx/conf.d/redirect_domain.conf.disabled: content: !Sub | server { server_name *.amazonaws.com; listen 80; return 301 http://${Domain}$request_uri; } commands: 01_install: command: amazon-linux-extras install nginx1.12 02_copy_conf: command: cp /usr/local/src/matreon/vendor/www/nginx.conf /etc/nginx/nginx.conf && cp /usr/local/src/matreon/vendor/www/matreon.conf /etc/nginx/conf.d && cp /usr/local/src/matreon/vendor/www/matreon/listen /etc/nginx/conf.d/matreon install_certbot: commands: 01_add_EPEL7: command: yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y 02_install: command: yum install -y python2-certbot-nginx 03_copy_https_upgrade_conf: command: cp /usr/local/src/matreon/vendor/www/https_upgrade.conf /etc/nginx/conf.d/https_upgrade.conf.disabled 04_add_cron_daily_at_random_time: command: echo "`shuf -i 00-59 -n 1` `shuf -i 00-23 -n 1` * * * /usr/bin/certbot renew --quiet" >> /usr/local/src/matreon/vendor/AWS/crontab-matreon prepare_cron_and_services: commands: 01_install_crontab: command: crontab -u matreon /usr/local/src/matreon/vendor/AWS/crontab-matreon 10_copy_systemd_files: command: cp /usr/local/src/matreon/vendor/**/*.service /lib/systemd/system && cp /usr/local/src/matreon/vendor/**/*.path /lib/systemd/system 11_prep_bitcoind_service: command: systemctl enable bitcoind.service && systemctl enable bitcoind.path && systemctl start bitcoind.path 12_start_ibd_and_prune_service: command: systemctl enable initial-blockchain-download.service && systemctl start initial-blockchain-download.service && systemctl enable ibd-shutdown.service && systemctl enable ibd-shutdown.path && systemctl start ibd-shutdown.path 13_prep__lightningd_service: command: systemctl enable lightningd.service && systemctl enable lightningd.path && systemctl start lightningd.path 14_prep__lightning_charge_service: command: systemctl enable lightning-charge.service && systemctl enable lightning-charge.path && systemctl start lightning-charge.path 15_run_rails_service: command: systemctl enable rails.service && systemctl start rails.service 16_run_nginx_service: command: systemctl enable nginx && systemctl start nginx 17_run_redirect_domain_service: command: !If - UseDomain - systemctl enable redirect-domain.service && systemctl start redirect-domain.service - echo 17_run_first_certificate_service: command: !If - SSL - systemctl enable first-certificate.service && systemctl start first-certificate.service - echo Properties: ImageId: ami-43eec3a8 InstanceType: i3.2xlarge BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: '25' VolumeType: 'gp2' - DeviceName: /dev/xvdb Ebs: VolumeSize: '40' VolumeType: 'standard' SecurityGroups: - !Ref 'WebServerSecurityGroup' KeyName: !Ref 'KeyName' Tags: - Key: Name Value: Matreon UserData: !Base64 Fn::Sub: | #!/bin/bash -xe yum update -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource WebServer --configsets full_install --region ${AWS::Region} /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource WebServer --region ${AWS::Region} CreationPolicy: ResourceSignal: Timeout: PT60M IPAddress: Type: AWS::EC2::EIP IPAssoc: Type: AWS::EC2::EIPAssociation Properties: InstanceId: !Ref 'WebServer' EIP: !Ref 'IPAddress' WebServerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: SSH, HTTP, Bitcoin & Lightning P2P SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '443' ToPort: '443' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: !If - NetworkBitcoin - '8883' - '18883' ToPort: !If - NetworkBitcoin - '8883' - '18883' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '9735' ToPort: '9735' CidrIp: 0.0.0.0/0 Outputs: IP: Value: !Sub '${WebServer.PublicIp}' Description: IP address to use for DNS A-Record WebsiteURL: Value: !Sub 'http://${WebServer.PublicDnsName}/' Description: URL for your Matreon