merge: deep
base_installation::system_users:
merge: unique
+ letsencrypt::hosts:
+ merge: unique
classes:
stdlib: ~
- host: "immae.eu"
key: "AAAAB3NzaC1yc2EAAAADAQABAAABAQDi5PgLBwMRyRwzJPnSgUyRAuB9AAxMijsw1pR/t/wmxQne1O5fIPOleHx+D8dyZbwm+XkzlcJpgT0Qy3qC9J8BPhshJvO/tA/8CI/oS/FE0uWsyACH1DMO2dk4gRRZGSE9IuzDMRPlnfZ3n0tdsPzzv3GH4It/oPIgsvkTowKztGLQ7Xmjr5BxzAhXcIQymqA0U3XWHSdWvnSRDaOFG0PDoVMS85IdwlviVKLnV5Sstb4NC/P28LFfgvW8DO/XrOqujgDomqTmR41dK/AyrGGOb2cQUMO4l8Oa+74aOyKaB61rr/rJkr+wCbEttkTvgFa6zZygSk3edfiWE2rgn4+v"
key_type: "ssh-rsa"
-xmr_stak::mining_pool: "pool.minexmr.com:7777"
-xmr_stak::wallet: "44CA8TxTFYbQqN2kLyk8AnB6Ghz4mcbGpYC2EyXW7A8H9QspvWnTjDn39XUZDPrFwPa5JNwt4TmAxcooPWv4SaJqL87Bcdo"
+profile::xmr_stak::mining_pool: "pool.minexmr.com:7777"
+profile::xmr_stak::wallet: "44CA8TxTFYbQqN2kLyk8AnB6Ghz4mcbGpYC2EyXW7A8H9QspvWnTjDn39XUZDPrFwPa5JNwt4TmAxcooPWv4SaJqL87Bcdo"
+letsencrypt::email: "sites+letsencrypt@mail.immae.eu"
+letsencrypt::try_for_real_hostname: true
---
classes:
role::cryptoportfolio: ~
-cryptoportfolio::slack_webhook: "%{ldapvar.self.vars.cf_slack_webhook.0}"
+letsencrypt::hosts: "%{lookup('base_installation::system_hostname')}"
+role::cryptoportfolio::user: "cryptoportfolio"
+role::cryptoportfolio::group: "cryptoportfolio"
+role::cryptoportfolio::home: "/home/cryptoportfolio"
+role::cryptoportfolio::env: "prod"
+role::cryptoportfolio::webhook_url: "%{ldapvar.self.vars.cf_slack_webhook.0}"
+role::cryptoportfolio::pg_db: "cryptoportfolio"
+role::cryptoportfolio::pg_user: "cryptoportfolio"
+role::cryptoportfolio::pg_user_replication: "cryptoportfolio_replication"
+role::cryptoportfolio::web_host: "%{lookup('base_installation::system_hostname')}"
+role::cryptoportfolio::web_port: ""
+role::cryptoportfolio::web_ssl: true
+base_installation::system_users:
+ - username: "%{lookup('role::cryptoportfolio::user')}"
+ system: true
+ password: "!!"
base_installation::system_hostname: "%{ldapvar.self.vars.host.0}"
base_installation::real_hostname: "%{facts.ec2_metadata.hostname}.v.immae.eu"
base_installation::ldap_cert_path: "/etc/ssl/certs/ca-certificates.crt"
-ssl::try_letsencrypt_for_real_hostname: true
+letsencrypt::try_for_real_hostname: true
base_installation::real_hostname: "%{facts.ec2_metadata.hostname}.ovh.net"
base_installation::grub_device: "/dev/sdb"
base_installation::ldap_cert_path: "/etc/ssl/certs/ca-certificates.crt"
-ssl::try_letsencrypt_for_real_hostname: false
+letsencrypt::try_for_real_hostname: false
---
-cryptoportfolio::front_version: v0.0.2-3-g6200f9a
-cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
-cryptoportfolio::bot_version: v0.5-8-g34eb08f
-cryptoportfolio::bot_sha256: f5b99c4a1cc4db0228f757705a5a909aa301e42787bc5842f8ba442fec0d3fd1
+role::cryptoportfolio::front_version: v0.0.2-3-g6200f9a
+role::cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
---
-cryptoportfolio::front_version: v0.0.2-3-g6200f9a
-cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
-cryptoportfolio::bot_version: v0.5.1
-cryptoportfolio::bot_sha256: 733789711365b2397bd996689af616a6789207d26c71a31ad1af68620b267d54
+role::cryptoportfolio::front_version: v0.0.2-3-g6200f9a
+role::cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
+role::cryptoportfolio::bot_version: v0.5.1
+role::cryptoportfolio::bot_sha256: 733789711365b2397bd996689af616a6789207d26c71a31ad1af68620b267d54
node default {
- lookup('classes', Hash, 'deep').each |$class_name, $class_hash| {
+ lookup('classes').each |$class_name, $class_hash| {
if empty($class_hash) {
include $class_name
} else {
require => File[$base_installation::puppet_conf_path],
}
- $ips = lookup("ips") |$key| { {} }
+ $ips = lookup("ips", { 'default_value' => undef })
file { "$base_installation::puppet_conf_path/host_ldap.info":
content => template("base_installation/puppet/host_ldap.info.erb"),
require => File[$base_installation::puppet_conf_path],
group => "root"
}
- $ip6 = lookup("ips.v6") |$key| { {} }
+ $ip6 = lookup("ips.v6", { 'default_value' => undef })
file { '/etc/systemd/network/en-dhcp.network':
ensure => "present",
path => "/etc/systemd/network/en-dhcp.network",
ensure => "present",
groups => $user[groups],
managehome => true,
+ system => !!$user[system],
home => "/home/${user[username]}",
- notify => Exec["remove_password"],
+ notify => Exec["remove_password:${user[username]}:${user[userid]}"],
purge_ssh_keys => true
}
- exec { "remove_password":
+ exec { "remove_password:${user[username]}:${user[userid]}":
command => "/usr/bin/chage -d 0 ${user[username]} && /usr/bin/passwd -d ${user[username]}",
+ onlyif => "/usr/bin/test -z '${user[password]}'",
refreshonly => true
}
- $user[keys].each |$key| {
- ssh_authorized_key { "${user[username]}@${key[host]}":
- name => "${user[username]}@${key[host]}",
- user => $user[username],
- type => $key[key_type],
- key => $key[key],
+ if has_key($user, "keys") {
+ $user[keys].each |$key| {
+ ssh_authorized_key { "${user[username]}@${key[host]}":
+ name => "${user[username]}@${key[host]}",
+ user => $user[username],
+ type => $key[key_type],
+ key => $key[key],
+ }
}
}
}
install_method => "package",
package_name => "certbot",
package_command => "certbot",
- # FIXME
- email => 'sites+letsencrypt@mail.immae.eu',
+ email => lookup('letsencrypt::email'),
}
- $real_hostname = lookup("base_installation::real_hostname") |$key| { {} }
+ $real_hostname = lookup("base_installation::real_hostname", { "default_value" => undef })
unless empty($real_hostname) {
- if (lookup("ssl::try_letsencrypt_for_real_hostname") |$key| { true }) {
+ if (lookup("letsencrypt::try_for_real_hostname", { "default_value" => true })) {
letsencrypt::certonly { $real_hostname:
before => Apache::Vhost["default_ssl"];
default: * => $::profile::apache::letsencrypt_certonly_default;
}
}
+ lookup("letsencrypt::hosts", { "default_value" => [] }).each |$host| {
+ if ($host != $real_hostname) { # Done above already
+ letsencrypt::certonly { $host: ;
+ default: * => $letsencrypt_certonly_default;
+ }
+ }
+ }
+
apache::vhost { "redirect_no_ssl":
port => '80',
error_log => false,
class profile::postgresql {
- $password_seed = lookup("base_installation::puppet_pass_seed") |$key| { {} }
+ $password_seed = lookup("base_installation::puppet_pass_seed")
class { '::postgresql::globals':
encoding => 'UTF-8',
database => 'all',
user => $pg_user,
auth_method => 'ident',
- order => "a1",
+ order => "00-01",
}
postgresql::server::pg_hba_rule { 'localhost access as postgres user':
description => 'Allow localhost access to postgres user',
user => $pg_user,
address => "127.0.0.1/32",
auth_method => 'md5',
- order => "a2",
+ order => "00-02",
}
postgresql::server::pg_hba_rule { 'localhost ip6 access as postgres user':
description => 'Allow localhost access to postgres user',
user => $pg_user,
address => "::1/128",
auth_method => 'md5',
- order => "a3",
+ order => "00-03",
}
postgresql::server::pg_hba_rule { 'deny access to postgresql user':
description => 'Deny remote access to postgres user',
user => $pg_user,
address => "0.0.0.0/0",
auth_method => 'reject',
- order => "a4",
+ order => "00-04",
}
postgresql::server::pg_hba_rule { 'local access':
database => 'all',
user => 'all',
auth_method => 'md5',
- order => "b1",
+ order => "10-01",
}
postgresql::server::pg_hba_rule { 'local access with same name':
database => 'all',
user => 'all',
auth_method => 'ident',
- order => "b2",
+ order => "10-02",
}
}
-class profile::xmr_stak {
+class profile::xmr_stak (
+ String $mining_pool,
+ String $wallet,
+ Optional[String] $password = "x",
+) {
ensure_resource('exec', 'systemctl daemon-reload', {
command => '/usr/bin/systemctl daemon-reload',
refreshonly => true
notify => Exec["systemctl daemon-reload"]
}
- $mining_pool = lookup("xmr_stak::mining_pool") |$key| { {} }
- $wallet = lookup("xmr_stak::wallet") |$key| { {} }
- $password = lookup("xmr_stak::password") |$key| { "x" }
- $instance = regsubst($facts["ec2_metadata"]["hostname"], '\.', "_", "G")
+ $instance = regsubst(lookup("base_installation::ldap_cn"), '\.', "_", "G")
file { "/var/lib/xmr_stak/xmr-stak.conf":
mode => "0644",
-class role::cryptoportfolio {
- ensure_resource('exec', 'systemctl daemon-reload', {
- command => '/usr/bin/systemctl daemon-reload',
- refreshonly => true
- })
-
+class role::cryptoportfolio (
+ String $user,
+ String $group,
+ String $home,
+ Optional[String] $env = "prod",
+ Optional[String] $webhook_url = undef,
+ String $pg_user,
+ String $pg_user_replication,
+ String $pg_db,
+ Optional[String] $pg_hostname = "localhost",
+ Optional[String] $pg_port = "5432",
+ Optional[String] $web_host = undef,
+ Optional[String] $web_port = "",
+ Optional[Boolean] $web_ssl = true,
+ Optional[String] $front_version = undef,
+ Optional[String] $front_sha256 = undef,
+ Optional[String] $bot_version = undef,
+ Optional[String] $bot_sha256 = undef,
+) {
include "base_installation"
include "profile::tools"
include "profile::apache"
include "profile::xmr_stak"
- $password_seed = lookup("base_installation::puppet_pass_seed") |$key| { {} }
-
- $cf_pg_user = "cryptoportfolio"
- $cf_pg_user_replication = "cryptoportfolio_replication"
- $cf_pg_db = "cryptoportfolio"
- $cf_pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
- $cf_pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication")
- $cf_pg_hostname = "localhost"
- $cf_pg_port = "5432"
- $cf_pg_host = "${cf_pg_hostname}:${cf_pg_port}"
-
- $cf_user = "cryptoportfolio"
- $cf_group = "cryptoportfolio"
- $cf_home = "/opt/cryptoportfolio"
- $cf_env = "prod"
- $cf_front_app_host = lookup("base_installation::system_hostname") |$key| { "example.com" }
- $cf_front_app_port = ""
- $cf_front_app_ssl = "true"
- $cf_front_app = "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front"
- $cf_front_app_api_workdir = "${cf_front_app}/cmd/app"
- $cf_front_app_api_bin = "${cf_front_app_api_workdir}/cryptoportfolio-app"
- $cf_front_app_api_conf = "${cf_home}/conf.toml"
- $cf_front_app_api_secret = generate_password(24, $password_seed, "cryptoportfolio_api_secret")
-
- $cf_front_app_static_conf = "${cf_front_app}/cmd/web/env/prod.env"
-
- $cf_bot_app = "${cf_home}/bot"
- $cf_bot_app_conf = "${cf_home}/bot_config.ini"
- $cf_bot_app_reports = "${cf_home}/bot_reports"
-
- $cf_webhook_url = lookup("cryptoportfolio::slack_webhook") |$key| { "" }
-
- file { "/var/lib/postgres/data/certs":
- ensure => directory,
- mode => "0700",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => File["/var/lib/postgres"],
- }
+ contain "role::cryptoportfolio::postgresql"
+ contain "role::cryptoportfolio::apache"
- file { "/var/lib/postgres/data/certs/cert.pem":
- source => "file:///etc/letsencrypt/live/$cf_front_app_host/cert.pem",
- mode => "0600",
- links => "follow",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]]
- }
-
- file { "/var/lib/postgres/data/certs/privkey.pem":
- source => "file:///etc/letsencrypt/live/$cf_front_app_host/privkey.pem",
- mode => "0600",
- links => "follow",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]]
- }
-
- postgresql::server::config_entry { "wal_level":
- value => "logical",
- }
-
- postgresql::server::config_entry { "ssl":
- value => "on",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::config_entry { "ssl_cert_file":
- value => "/var/lib/postgres/data/certs/cert.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::config_entry { "ssl_key_file":
- value => "/var/lib/postgres/data/certs/privkey.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::db { $cf_pg_db:
- user => $cf_pg_user,
- password => postgresql_password($cf_pg_user, $cf_pg_password),
- }
- ->
- postgresql_psql { "CREATE PUBLICATION ${cf_pg_db}_publication FOR ALL TABLES":
- db => $cf_pg_db,
- unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${cf_pg_db}_publication'",
- }
- ->
- postgresql::server::role { $cf_pg_user_replication:
- db => $cf_pg_db,
- replication => true,
- password_hash => postgresql_password($cf_pg_user_replication, $cf_pg_replication_password),
- }
- ->
- postgresql::server::database_grant { $cf_pg_user_replication:
- db => $cf_pg_db,
- privilege => "CONNECT",
- role => $cf_pg_user_replication,
- }
- ->
- postgresql::server::grant { "all tables in schema:public:$cf_pg_user_replication":
- db => $cf_pg_db,
- role => $cf_pg_user_replication,
- privilege => "SELECT",
- object_type => "ALL TABLES IN SCHEMA",
- object_name => "public",
- }
- ->
- postgresql::server::grant { "all sequences in schema:public:$cf_pg_user_replication":
- db => $cf_pg_db,
- role => $cf_pg_user_replication,
- privilege => "SELECT",
- object_type => "ALL SEQUENCES IN SCHEMA",
- object_name => "public",
- }
-
- postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user':
- type => 'host',
- database => $cf_pg_db,
- user => $cf_pg_user,
- address => '127.0.0.1/32',
- auth_method => 'md5',
- order => "b0",
- }
- postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user':
- type => 'host',
- database => $cf_pg_db,
- user => $cf_pg_user,
- address => '::1/128',
- auth_method => 'md5',
- order => "b0",
- }
-
- postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu':
- type => 'hostssl',
- database => $cf_pg_db,
- user => $cf_pg_user_replication,
- address => 'immae.eu',
- auth_method => 'md5',
- order => "b0",
- }
-
- letsencrypt::certonly { $cf_front_app_host: ;
- default: * => $::profile::apache::letsencrypt_certonly_default;
- }
-
- class { 'apache::mod::headers': }
- apache::vhost { $cf_front_app_host:
- port => '443',
- docroot => false,
- manage_docroot => false,
- proxy_dest => "http://localhost:8000",
- request_headers => 'set X-Forwarded-Proto "https"',
- ssl => true,
- ssl_cert => "/etc/letsencrypt/live/$cf_front_app_host/cert.pem",
- ssl_key => "/etc/letsencrypt/live/$cf_front_app_host/privkey.pem",
- ssl_chain => "/etc/letsencrypt/live/$cf_front_app_host/chain.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- proxy_preserve_host => true;
- default: * => $::profile::apache::apache_vhost_default;
- }
-
- user { $cf_user:
- name => $cf_user,
- ensure => "present",
- managehome => true,
- home => $cf_home,
- system => true,
- password => '!!',
- }
-
- file { "/usr/local/bin/slack-notify":
- mode => "0755",
- source => "puppet:///modules/role/cryptoportfolio/slack-notify.py",
- }
-
- $front_version = lookup("cryptoportfolio::front_version") |$key| { {} }
- $front_sha256 = lookup("cryptoportfolio::front_sha256") |$key| { {} }
-
- $bot_version = lookup("cryptoportfolio::bot_version") |$key| { {} }
- $bot_sha256 = lookup("cryptoportfolio::bot_sha256") |$key| { {} }
+ contain "role::cryptoportfolio::notify"
unless empty($bot_version) {
- ensure_packages(["python", "python-pip"])
-
- file { $cf_bot_app:
- ensure => "directory",
- mode => "0700",
- owner => $cf_user,
- group => $cf_group,
- require => User[$cf_user],
- }
-
- archive { "${cf_home}/trader_${bot_version}.tar.gz":
- path => "${cf_home}/trader_${bot_version}.tar.gz",
- source => "https://git.immae.eu/releases/cryptoportfolio/trader/trader_${bot_version}.tar.gz",
- checksum_type => "sha256",
- checksum => $bot_sha256,
- cleanup => false,
- extract => true,
- user => $cf_user,
- username => $facts["ec2_metadata"]["hostname"],
- password => generate_password(24, $password_seed, "ldap"),
- extract_path => $cf_bot_app,
- require => [User[$cf_user], File[$cf_bot_app]],
- } ~>
- exec { "py-cryptoportfolio-dependencies":
- cwd => $cf_bot_app,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make install",
- require => User[$cf_user],
- refreshonly => true,
- before => [
- File[$cf_bot_app_conf],
- Cron["py-cryptoportfolio-before"],
- Cron["py-cryptoportfolio-after"],
- ]
- }
-
- file { $cf_bot_app_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/bot_config.ini.erb"),
- require => [
- User[$cf_user],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"],
- ],
- }
-
- cron { "py-cryptoportfolio-before":
- ensure => present,
- command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --before",
- user => "cryptoportfolio",
- weekday => 7, # Sunday
- hour => 22,
- minute => 30,
- environment => ["HOME=${cf_home}","PATH=/usr/bin/"],
- require => [
- File[$cf_bot_app_conf],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"]
- ],
- }
-
- cron { "py-cryptoportfolio-after":
- ensure => present,
- command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --after",
- user => "cryptoportfolio",
- weekday => 1, # Monday
- hour => 1,
- minute => 0,
- environment => ["HOME=${cf_home}","PATH=/usr/bin/"],
- require => [
- File[$cf_bot_app_conf],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"]
- ],
- }
-
- unless empty($cf_webhook_url) {
- exec { "bot-slack-notify":
- refreshonly => true,
- environment => [
- "P_PROJECT=Trader",
- "P_WEBHOOK=${cf_webhook_url}",
- "P_VERSION=${bot_version}",
- "P_HOST=${cf_front_app_host}",
- "P_HTTPS=${cf_front_app_ssl}",
- ],
- command => "/usr/local/bin/slack-notify",
- require => File["/usr/local/bin/slack-notify"],
- subscribe => Exec["py-cryptoportfolio-dependencies"],
- }
- }
+ contain "role::cryptoportfolio::bot"
}
# FIXME: restore backup
unless empty($front_version) {
- ensure_packages(["go", "npm", "nodejs", "yarn"])
-
- file { [
- "${cf_home}/go/",
- "${cf_home}/go/src",
- "${cf_home}/go/src/immae.eu",
- "${cf_home}/go/src/immae.eu/Immae",
- "${cf_home}/go/src/immae.eu/Immae/Projets",
- "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies",
- "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio",
- $cf_front_app]:
- ensure => "directory",
- mode => "0700",
- owner => $cf_user,
- group => $cf_group,
- require => User[$cf_user],
- }
-
- file { "${cf_home}/front":
- ensure => "link",
- target => $cf_front_app,
- before => File[$cf_front_app],
- }
-
- file { "/etc/systemd/system/cryptoportfolio-app.service":
- mode => "0644",
- owner => "root",
- group => "root",
- content => template("role/cryptoportfolio/cryptoportfolio-app.service.erb"),
- notify => Exec["systemctl daemon-reload"],
- }
-
- service { 'cryptoportfolio-app':
- enable => true,
- ensure => "running",
- subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
- require => [
- File["/etc/systemd/system/cryptoportfolio-app.service"],
- Postgresql::Server::Db[$cf_pg_db]
- ],
- } ~>
- exec { "dump $cf_pg_db structure":
- refreshonly => true,
- user => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- command => "/usr/bin/pg_dump --schema-only --clean --no-publications $cf_pg_db > /var/lib/postgres/${cf_pg_db}.schema",
- }
-
- archive { "${cf_home}/front_${front_version}.tar.gz":
- path => "${cf_home}/front_${front_version}.tar.gz",
- source => "https://git.immae.eu/releases/cryptoportfolio/front/front_${front_version}.tar.gz",
- checksum_type => "sha256",
- checksum => $front_sha256,
- cleanup => false,
- extract => true,
- user => $cf_user,
- username => $facts["ec2_metadata"]["hostname"],
- password => generate_password(24, $password_seed, "ldap"),
- extract_path => $cf_front_app,
- require => [User[$cf_user], File[$cf_front_app]],
- notify => [
- Exec["web-cryptoportfolio-dependencies"],
- Exec["go-get-dep"],
- ]
- }
-
- # Api
- file { $cf_front_app_api_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/api_conf.toml.erb"),
- before => Exec["go-cryptoportfolio-app"],
- }
-
- exec { "go-get-dep":
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- creates => "${cf_home}/go/bin/dep",
- command => "/usr/bin/go get -u github.com/golang/dep/cmd/dep",
- refreshonly => true,
- } ~>
- exec { "go-cryptoportfolio-dependencies":
- cwd => $cf_front_app,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "${cf_home}/go/bin/dep ensure",
- refreshonly => true,
- } ~>
- exec { "go-cryptoportfolio-app":
- cwd => $cf_front_app_api_workdir,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make build",
- refreshonly => true,
- }
-
- # Static pages
- file { $cf_front_app_static_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/static_conf.env.erb"),
- before => Exec["web-cryptoportfolio-build"],
- }
-
- exec { "web-cryptoportfolio-dependencies":
- cwd => "${cf_front_app}/cmd/web",
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make install",
- refreshonly => true,
- require => [Package["npm"], Package["nodejs"], Package["yarn"]]
- } ~>
- exec { "web-cryptoportfolio-build":
- cwd => "${cf_front_app}/cmd/web",
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- path => ["${cf_front_app}/cmd/web/node_modules/.bin/", "/usr/bin"],
- command => "/usr/bin/make static ENV=${cf_env}",
- refreshonly => true,
- }
-
- unless empty($cf_webhook_url) {
- exec { "front-slack-notify":
- refreshonly => true,
- environment => [
- "P_PROJECT=Front",
- "P_WEBHOOK=${cf_webhook_url}",
- "P_VERSION=${front_version}",
- "P_HOST=${cf_front_app_host}",
- "P_HTTPS=${cf_front_app_ssl}",
- ],
- command => "/usr/local/bin/slack-notify",
- require => File["/usr/local/bin/slack-notify"],
- subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
- }
- }
+ contain "role::cryptoportfolio::front"
}
}
--- /dev/null
+class role::cryptoportfolio::apache inherits role::cryptoportfolio {
+ class { 'apache::mod::headers': }
+ apache::vhost { $web_host:
+ port => '443',
+ docroot => false,
+ manage_docroot => false,
+ proxy_dest => "http://localhost:8000",
+ request_headers => 'set X-Forwarded-Proto "https"',
+ ssl => true,
+ ssl_cert => "/etc/letsencrypt/live/$web_host/cert.pem",
+ ssl_key => "/etc/letsencrypt/live/$web_host/privkey.pem",
+ ssl_chain => "/etc/letsencrypt/live/$web_host/chain.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ proxy_preserve_host => true;
+ default: * => $::profile::apache::apache_vhost_default;
+ }
+}
--- /dev/null
+class role::cryptoportfolio::bot inherits role::cryptoportfolio {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $cf_bot_app = "${home}/bot"
+ $cf_bot_app_conf = "${home}/bot_config.ini"
+ $cf_bot_app_reports = "${home}/bot_reports"
+
+ ensure_packages(["python", "python-pip"])
+
+ file { $cf_bot_app:
+ ensure => "directory",
+ mode => "0700",
+ owner => $user,
+ group => $group,
+ require => User["$user:"],
+ }
+
+ archive { "${home}/trader_${bot_version}.tar.gz":
+ path => "${home}/trader_${bot_version}.tar.gz",
+ source => "https://git.immae.eu/releases/cryptoportfolio/trader/trader_${bot_version}.tar.gz",
+ checksum_type => "sha256",
+ checksum => $bot_sha256,
+ cleanup => false,
+ extract => true,
+ user => $user,
+ username => lookup("base_installation::ldap_cn"),
+ password => generate_password(24, $password_seed, "ldap"),
+ extract_path => $cf_bot_app,
+ require => [User["$user:"], File[$cf_bot_app]],
+ } ~>
+ exec { "py-cryptoportfolio-dependencies":
+ cwd => $cf_bot_app,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make install",
+ require => User["$user:"],
+ refreshonly => true,
+ before => [
+ File[$cf_bot_app_conf],
+ Cron["py-cryptoportfolio-before"],
+ Cron["py-cryptoportfolio-after"],
+ ]
+ }
+
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ file { $cf_bot_app_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/bot_config.ini.erb"),
+ require => [
+ User["$user:"],
+ Archive["${home}/trader_${bot_version}.tar.gz"],
+ ],
+ }
+
+ cron { "py-cryptoportfolio-before":
+ ensure => present,
+ command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --before",
+ user => $user,
+ weekday => 7, # Sunday
+ hour => 22,
+ minute => 30,
+ environment => ["HOME=${home}","PATH=/usr/bin/"],
+ require => [
+ File[$cf_bot_app_conf],
+ Archive["${home}/trader_${bot_version}.tar.gz"]
+ ],
+ }
+
+ cron { "py-cryptoportfolio-after":
+ ensure => present,
+ command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --after",
+ user => $user,
+ weekday => 1, # Monday
+ hour => 1,
+ minute => 0,
+ environment => ["HOME=${home}","PATH=/usr/bin/"],
+ require => [
+ File[$cf_bot_app_conf],
+ Archive["${home}/trader_${bot_version}.tar.gz"]
+ ],
+ }
+
+ unless empty($webhook_url) {
+ exec { "bot-slack-notify":
+ refreshonly => true,
+ environment => [
+ "P_PROJECT=Trader",
+ "P_WEBHOOK=${webhook_url}",
+ "P_VERSION=${bot_version}",
+ "P_HOST=${web_host}",
+ "P_HTTPS=${web_ssl}",
+ ],
+ command => "/usr/local/bin/slack-notify",
+ require => File["/usr/local/bin/slack-notify"],
+ subscribe => Exec["py-cryptoportfolio-dependencies"],
+ }
+ }
+}
+
--- /dev/null
+class role::cryptoportfolio::front inherits role::cryptoportfolio {
+ ensure_resource('exec', 'systemctl daemon-reload', {
+ command => '/usr/bin/systemctl daemon-reload',
+ refreshonly => true
+ })
+
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $cf_front_app = "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front"
+ $cf_front_app_api_workdir = "${cf_front_app}/cmd/app"
+ $cf_front_app_api_bin = "${cf_front_app_api_workdir}/cryptoportfolio-app"
+ $cf_front_app_api_conf = "${home}/conf.toml"
+ $cf_front_app_api_secret = generate_password(24, $password_seed, "cryptoportfolio_api_secret")
+
+ $cf_front_app_static_conf = "${cf_front_app}/cmd/web/env/prod.env"
+
+ ensure_packages(["go", "npm", "nodejs", "yarn"])
+
+ file { [
+ "${home}/go/",
+ "${home}/go/src",
+ "${home}/go/src/immae.eu",
+ "${home}/go/src/immae.eu/Immae",
+ "${home}/go/src/immae.eu/Immae/Projets",
+ "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies",
+ "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio",
+ $cf_front_app]:
+ ensure => "directory",
+ mode => "0700",
+ owner => $user,
+ group => $group,
+ require => User["$user:"],
+ }
+
+ file { "${home}/front":
+ ensure => "link",
+ target => $cf_front_app,
+ before => File[$cf_front_app],
+ }
+
+ file { "/etc/systemd/system/cryptoportfolio-app.service":
+ mode => "0644",
+ owner => "root",
+ group => "root",
+ content => template("role/cryptoportfolio/cryptoportfolio-app.service.erb"),
+ notify => Exec["systemctl daemon-reload"],
+ }
+
+ service { 'cryptoportfolio-app':
+ enable => true,
+ ensure => "running",
+ subscribe => [File[$cf_front_app_api_conf], Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
+ require => [
+ File["/etc/systemd/system/cryptoportfolio-app.service"],
+ Postgresql::Server::Db[$pg_db]
+ ],
+ } ~>
+ exec { "dump $pg_db structure":
+ refreshonly => true,
+ user => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ command => "/usr/bin/pg_dump --schema-only --clean --no-publications $pg_db > /var/lib/postgres/${pg_db}.schema",
+ }
+
+ archive { "${home}/front_${front_version}.tar.gz":
+ path => "${home}/front_${front_version}.tar.gz",
+ source => "https://git.immae.eu/releases/cryptoportfolio/front/front_${front_version}.tar.gz",
+ checksum_type => "sha256",
+ checksum => $front_sha256,
+ cleanup => false,
+ extract => true,
+ user => $user,
+ username => lookup("base_installation::ldap_cn"),
+ password => generate_password(24, $password_seed, "ldap"),
+ extract_path => $cf_front_app,
+ require => [User["$user:"], File[$cf_front_app]],
+ notify => [
+ Exec["web-cryptoportfolio-dependencies"],
+ Exec["go-get-dep"],
+ ]
+ }
+
+ # Api
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ $pg_host = "${pg_hostname}:${pg_port}"
+ file { $cf_front_app_api_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/api_conf.toml.erb"),
+ before => Exec["go-cryptoportfolio-app"],
+ }
+
+ exec { "go-get-dep":
+ user => $user,
+ environment => ["HOME=${home}"],
+ creates => "${home}/go/bin/dep",
+ command => "/usr/bin/go get -u github.com/golang/dep/cmd/dep",
+ refreshonly => true,
+ } ~>
+ exec { "go-cryptoportfolio-dependencies":
+ cwd => $cf_front_app,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "${home}/go/bin/dep ensure",
+ refreshonly => true,
+ } ~>
+ exec { "go-cryptoportfolio-app":
+ cwd => $cf_front_app_api_workdir,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make build",
+ refreshonly => true,
+ }
+
+ # Static pages
+ file { $cf_front_app_static_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/static_conf.env.erb"),
+ before => Exec["web-cryptoportfolio-build"],
+ }
+
+ exec { "web-cryptoportfolio-dependencies":
+ cwd => "${cf_front_app}/cmd/web",
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make install",
+ refreshonly => true,
+ require => [Package["npm"], Package["nodejs"], Package["yarn"]]
+ } ~>
+ exec { "web-cryptoportfolio-build":
+ cwd => "${cf_front_app}/cmd/web",
+ user => $user,
+ environment => ["HOME=${home}"],
+ path => ["${cf_front_app}/cmd/web/node_modules/.bin/", "/usr/bin"],
+ command => "/usr/bin/make static ENV=${env}",
+ refreshonly => true,
+ }
+
+ unless empty($webhook_url) {
+ exec { "front-slack-notify":
+ refreshonly => true,
+ environment => [
+ "P_PROJECT=Front",
+ "P_WEBHOOK=${webhook_url}",
+ "P_VERSION=${front_version}",
+ "P_HOST=${web_host}",
+ "P_HTTPS=${web_ssl}",
+ ],
+ command => "/usr/local/bin/slack-notify",
+ require => File["/usr/local/bin/slack-notify"],
+ subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
+ }
+ }
+
+}
--- /dev/null
+class role::cryptoportfolio::notify inherits role::cryptoportfolio {
+ file { "/usr/local/bin/slack-notify":
+ mode => "0755",
+ source => "puppet:///modules/role/cryptoportfolio/slack-notify.py",
+ }
+}
--- /dev/null
+class role::cryptoportfolio::postgresql inherits role::cryptoportfolio {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ $pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication")
+
+ file { "/var/lib/postgres/data/certs":
+ ensure => directory,
+ mode => "0700",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => File["/var/lib/postgres"],
+ }
+
+ file { "/var/lib/postgres/data/certs/cert.pem":
+ source => "file:///etc/letsencrypt/live/$web_host/cert.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]]
+ }
+
+ file { "/var/lib/postgres/data/certs/privkey.pem":
+ source => "file:///etc/letsencrypt/live/$web_host/privkey.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]]
+ }
+
+ postgresql::server::config_entry { "wal_level":
+ value => "logical",
+ }
+
+ postgresql::server::config_entry { "ssl":
+ value => "on",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::config_entry { "ssl_cert_file":
+ value => "/var/lib/postgres/data/certs/cert.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::config_entry { "ssl_key_file":
+ value => "/var/lib/postgres/data/certs/privkey.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::db { $pg_db:
+ user => $pg_user,
+ password => postgresql_password($pg_user, $pg_password),
+ }
+ ->
+ postgresql_psql { "CREATE PUBLICATION ${pg_db}_publication FOR ALL TABLES":
+ db => $pg_db,
+ unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${pg_db}_publication'",
+ }
+ ->
+ postgresql::server::role { $pg_user_replication:
+ db => $pg_db,
+ replication => true,
+ password_hash => postgresql_password($pg_user_replication, $pg_replication_password),
+ }
+ ->
+ postgresql::server::database_grant { $pg_user_replication:
+ db => $pg_db,
+ privilege => "CONNECT",
+ role => $pg_user_replication,
+ }
+ ->
+ postgresql::server::grant { "all tables in schema:public:$pg_user_replication":
+ db => $pg_db,
+ role => $pg_user_replication,
+ privilege => "SELECT",
+ object_type => "ALL TABLES IN SCHEMA",
+ object_name => "public",
+ }
+ ->
+ postgresql::server::grant { "all sequences in schema:public:$pg_user_replication":
+ db => $pg_db,
+ role => $pg_user_replication,
+ privilege => "SELECT",
+ object_type => "ALL SEQUENCES IN SCHEMA",
+ object_name => "public",
+ }
+
+ postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user':
+ type => 'host',
+ database => $pg_db,
+ user => $pg_user,
+ address => '127.0.0.1/32',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+ postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user':
+ type => 'host',
+ database => $pg_db,
+ user => $pg_user,
+ address => '::1/128',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+
+ postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu':
+ type => 'hostssl',
+ database => $pg_db,
+ user => $pg_user_replication,
+ address => 'immae.eu',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+
+}
log_level="info"
-mode="<%= @cf_env %>"
+mode="<%= @env %>"
log_out="stdout"
[db]
-user="<%= @cf_pg_user %>"
-password="<%= @cf_pg_password %>"
-database="<%= @cf_pg_db %>"
-address="<%= @cf_pg_host %>"
+user="<%= @pg_user %>"
+password="<%= @pg_password %>"
+database="<%= @pg_db %>"
+address="<%= @pg_host %>"
[api]
-domain="<%= @cf_front_app_host %>"
+domain="<%= @web_host %>"
jwt_secret="<%= @cf_front_app_api_secret %>"
[app]
[postgresql]
-host = <%= @cf_pg_hostname %>
-port = <%= @cf_pg_port %>
-user = <%= @cf_pg_user %>
-password = <%= @cf_pg_password %>
-database = <%= @cf_pg_db %>
+host = <%= @pg_hostname %>
+port = <%= @pg_port %>
+user = <%= @pg_user %>
+password = <%= @pg_password %>
+database = <%= @pg_db %>
[app]
report_path = <%= @cf_bot_app_reports %>
Type=simple
WorkingDirectory=<%= @cf_front_app_api_workdir %>
-User=<%= @cf_user %>
-Group=<%= @cf_group %>
+User=<%= @user %>
+Group=<%= @group %>
UMask=007
ExecStart=<%= @cf_front_app_api_bin %> -conf <%= @cf_front_app_api_conf %>
-API_HOST="<%= @cf_front_app_host %>"
-API_PORT="<%= @cf_front_app_port %>"
-API_HTTPS="<%= @cf_front_app_ssl %>"
+API_HOST="<%= @web_host %>"
+API_PORT="<%= @web_port %>"
+API_HTTPS="<%= @web_ssl %>"