Files @ a717a6ccd782
Branch filter:

Location: majic-ansible-roles/docs/rolereference.rst

a717a6ccd782 69.6 KiB text/prs.fallenstein.rst Show Annotation Show as Raw Download as Raw
branko
MAR-65: Disable Emacs electric-indent-mode by default via common role (if Emacs is installed via common_packages).
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
.. _rolereference:

Role Reference
==============


Common parameters
-----------------

A number of common parameters are used by all of the roles during
deployment. This section lists such parameters.

**enable_backup** (boolean, optional, ``False``)
  If set to ``True``, and the role supports backups, server will be configured
  for back-up of role's data. See role description for more details on what is
  backed-up and if the option is available. Just keep in mind that if you enable
  this globally, all the roles will be running backup-specific tasks. If the
  option has been enabled, the ``backup_client`` role will be included
  automatically (see the role reference for details on parameters that need to
  be provided in the case).

**tls_private_key_dir** (string, optional if paths to private keys for all roles are explicitly specified)
  Path to directory on Ansible host that contains the private keys used by
  services deployed by various roles. When TLS keys are not explicitly defined
  in a role, this is the directory where the TLS key will be looked-up during
  Ansible run. Expected filename pattern is ``FQDN_SERVICE.key`` (for example,
  ``mail.example.com_smtp.key`` or ``xmpp.example.com_xmpp.key``).

**tls_certificate_dir** (string, optional if paths to certificate files for all roles are explicitly specified)
  Path to directory on Ansible host that contains the X.509 certificate files
  used by services deployed by various roles. When X.509 certificate is not
  explicitly defined in a role, this is the directory where the X.509
  certificate will be looked-up during Ansible run. Expected filename pattern is
  ``FQDN_SERVICE.pem`` (for example, ``mail.example.com_smtp.pem`` or
  ``xmpp.example.com_xmpp.pem``).


Preseed
-------

The ``preseed`` role can be used for generating simple preseed files for Debian
Wheezy installations.

The generated preseed files allow simplified installation, with a single root
partition. There is a number of parameters that allow for customising the
content of preseed files.

It is possible to specify parameter values that should be used for all servers,
as well for individual servers. It is also possible to combine this approach,
defining global parameters that get overridden per server.

The role will by default process all hosts from the inventory, generating one
preseed file per server.


Parameters
~~~~~~~~~~

**ansible_key** (string, optional, ``{{ lookup('file', '~/.ssh/id_rsa.pub') }}``)
  SSH public key that should be deployed to authorized_keys truststore for
  operating system user ``root``. This is necessary for the bootstrap process
  to work since Debian Jessie does not allow password-based logins for root.

**preseed_country** (string, optional, ``SE``)
  Country.

**preseed_directory** (string, optional, ``../preseed_files/``)
  Destination directory where the preseed files should be stored.

  .. warning::
     Do not name this directory ``preseed`` if it lies on a path where Ansible
     would normally look-up the roles (it will conflict with the role name).

**preseed_dns** (string, mandatory if **preseed_network_auto** is ``no``)
  Comma-separated list of DNS servers.

**preseed_domain** (string, mandatory if **preseed_network_auto** is ``no``)
  Server domain.

**preseed_gateway** (string, mandatory if **preseed_network_auto** is ``no``)
  Default gateway for the server.

**preseed_hostname** (string, mandatory if **preseed_network_auto** is ``no``)
  Server hostname.

**preseed_ip** (string, mandatory if **preseed_network_auto** is ``no``)
  IP address for the server network interface.

**preseed_keymap** (string, optional, ``us``)
  Keymap.

**preseed_language** (string, optional, ``en``)
  Language.

**preseed_locale** (string, optional, ``en_US.UTF-8``)
  Locale.

**preseed_mirror_directory** (string, optional, ``/debian``)
  Directory under which the Debian apt repositories can be found on the
  specified mirror.

**preseed_mirror_hostname** (string, optional, ``ftp.se.debian.org``)
  Resolvable hostname of FQDN where the Debian apt repositories can be
  found. Only HTTP mirrors are supported.

**preseed_mirror_proxy** (string, optional, ``None``)
  An HTTP proxy that should be used for accessing the Debian apt
  repositories.

**preseed_netmask** (string, mandatory if **preseed_network_auto** is ``no``)
  Netmask for the server network interface.

**preseed_network_auto** (boolean, optional, ``yes``)
  Specifies whether the network configuration should be automatic (using DHCP)
  or manual. If manual configuration is selected a number of additional options
  needs to be specified: ``preseed_hostname``, ``preseed_domain``,
  ``preseed_ip``, ``preseed_netmask``, ``preseed_gateway``,
  ``preseed_dns``. For some of these values you may want to use per-server
  overrides - see parameter ``preseed_server_overrides``.

**preseed_network_interface** (string, optional, ``eth0``)
  Name of network interface (for example ``eth0``, ``eth1`` etc) that should be
  configured.

**preseed_root_password** (string, optional, ``root``)
  Initial password that should be set for the server during the installation.

**preseed_server_overrides** (string, optional, ``{}``)
  A dictionary consisting out of one or more entries where individual values for
  preseed files can be overridden per-server. Each entry's key should be the
  name of the server, as specified in the inventory. Each value should also be a
  dictionary, where valid keys are: ``country``, ``dns``, ``domain``,
  ``gateway``, ``hostname``, ``ip``, ``keymap``, ``language``, ``locale``,
  ``mirror_directory``, ``mirror_hostname``, ``mirror_proxy``, ``netmask``,
  ``network_auto``, ``network_interface``, ``root_password``,
  ``timezone``. These have the same meaning as their ``preseed_`` counterparts.

**preseed_timezone** (string, optional, ``Europe/Stockholm``)
  Timezone that should be used when calculating server time. It is assumed that
  the local hardware clock is set to UTC.


Examples
~~~~~~~~

Here is an example configuration for a preseed file that sets some global
defaults to be used for all servers, and then overrides it for one server:

.. code-block:: yaml

  ---

  ansible_key: {{ lookup('file', '~/.ssh/id_rsa.pub') }}
  preseed_country: UK
  preseed_directory: /var/www/preseed
  preseed_keymap: UK
  preseed_language: en
  preseed_locale: en_UK.UTF-8
  preseed_mirror_directory: /debian
  preseed_mirror_hostname: ftp.uk.debian.org
  preseed_mirror_proxy: ""
  preseed_network_auto: yes
  preseed_network_interface: eth0
  preseed_root_password: secret
  preseed_timezone: Europe/London
  preseed_server_overrides:
    ldap.example.com:
      network_auto: no
      hostname: ldap
      domain: example.com
      ip: 192.168.1.20
      netmask: 255.255.255.0
      gateway: 192.168.1.1
      dns: 192.168.1.1,192.168.1.2
      timezone: Europe/Stockholm


Bootstrap
---------

The ``bootstrap`` role can be used for bootstraping a new server with
Ansible. In order to apply this role to a server, all that is necessary is root
access to the server (either via SSH or locally).

The role implements the following:

* Installs sudo package.
* Creates operating system user and group for Ansible (``ansible``).
* Sets-up an authorized_key for operating system user ``ansible`` (for remote
  SSH access).
* Configures sudo to allow operating system user ``ansible`` to run sudo
  commands without password authentication.
* Removes the Ansible user's key from the list of authorized keys for user root
  at the end of bootstrap process. This key was necessary only for the bootstrap
  process.


Parameters
~~~~~~~~~~

**ansible_key** (string, optional, ``{{ lookup('file', '~/.ssh/id_rsa.pub') }}``)
  SSH public key that should be deployed to authorized_keys truststore for
  operating system user ``ansible``.


Examples
~~~~~~~~

Since the role is meant to be used just after the server has been installed, and
using the ``root`` account, it is probably going to be invoked from a separate
playbook.

For example, a playbook (``bootstrap.yml``) could look something similar to:

.. code-block:: yaml

  ---

  - hosts: "{{ server }}"
    remote_user: root
    roles:
      - bootstrap
    vars:
      ansible_key: "{{ lookup('file', 'authorized_keys/ansible.pub') }}"

With such a playbook in place, it would be invoked with:

  ansible-playbook --ask-pass -e server=test1.example.com bootstrap.yml


Common
------

The ``common`` role can be used for applying a common configuration and
hardening across all servers, no matter what services they provide.

The role implements the following:

* Configures apt to use caching proxy (if any was specified).
* Sets-up umask for all logins to ``0027``.
* Installs sudo.
* Sets-up uniform bash prompt for all accounts (optionally coloured and with
  identifier). This is useful for distinguishing machines and/or environments.
* Installs additional base packages, as configured.
* Disables ``electric-indent-mode`` in Emacs globally if either the ``emacs24``
  or ``emacs24-nox`` are installed through the role.
* Creates additional operating system groups, as configured.
* Creates additional operating system users, as configured.
* Hardens the SSH server by disabling remote ``root`` logins and password-based
  authentication.
* Allows traversing of directory ``/etc/ssl/private/`` to everyone. This lets
  you put TLS private keys in central location where any operating system user
  can reach them provided they have appropriate read/write rights on the file
  itself, and provided they know the exact path of the file.
* Deploys CA certificate files, normally used for truststore purposes, to
  ``/usr/local/share/ca-certificates/``.
* Installs ``ferm`` (for iptables management), configuring a basic firewall
  which allows ICMP echo requests (PING), incoming connection on TCP port 22
  (SSH), and also introduces rate-limitting for incoming ICMP echo request
  pacakges and (new) TCP connections. The rate-limitting is based on the source
  IP address, using the ``iptables hashlimit`` module.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **backup_client**


Backups
~~~~~~~

If the backup for this role has been enabled, the following paths are backed-up:

**/var/log**
  Log files from the system.

**/home**
  Home directory for regular users.

**/root**
  Root user's home directory.


Parameters
~~~~~~~~~~

**apt_proxy** (string, optional, ``None``)
  URI of a caching proxy that should be used when retrieving the packages via
  apt.

**os_users** (list, optional, ``[]``)
  A list of operating system users that should be set-up on a server. Each item
  is a dictionary with the following options describing the user parameters:

  **name** (string, mandatory)
    Name of the operating system user that should be created. User's default
    group will have the same name as the user.

  **uid** (number, optional, ``whatever OS picks``)
    UID for the operating system user. User's default group will have a GID
    identical to the user's UID if specified. Otherwise user's default group
    will have OS-determined GID.

  **additional_groups** (list, optional, ``[]``)
    Comma-separated list of additional groups that a user should belong to.

  **authorized_keys** (list, optional, ``[]``)
    List of SSH public keys that should be deployed to user's authorized_keys
    truststore.

  **password** (string, optional, ``!`` - no password)
    Encrypted password that should be set for the user.

**os_groups** (list, optional, ``[]``)
  A list of operating system groups that should be set-up on a server. Each item
  is a dictionary with the following options describing the group parameters:

  **name** (string, mandatory)
    Name of the operating system group that should be created.

  **gid** (number, optional, ``whatever OS picks``)
    GID for the operating system group.

**common_packages** (list, optional, ``[]``)
  List of additional operating system packages that should be installed on the
  server. Each element of the list should be a simple string denoting the name
  of the package.

**ca_certificates** (list, optional, ``{}``)
  Dictionary containing the CA certificates to deploy. Keys are base filenames
  (**without extension**) to be used when placing a certificate file in
  directory ``/usr/local/share/ca-certificates/``, while values are
  corresponding content to be placed in the file.

**incoming_connection_limit** (string, optional, ``3/second``)
  Rate at which the incoming ICMP echo-request packages and new TCP connections
  will be accepted at. The value should be specified in the same format as value
  for the ``iptables hashlimit`` option ``--hashlimit-upto``.

**incoming_connection_limit_burst** (string, optional, ``9``)
  Initial burst of packages that should be accepted when the client with
  distinct source IP address connects to the server for the first time (usually
  higher than ``incoming_connection_limit``), even if it would go above the
  specified connection limit.

**prompt_colour** (string, optional, ``none``)
  Colour for showing the Bash prompt. Supported values are:

  ``black``, ``red``, ``green``, ``brown``, ``blue``, ``purple``, ``cyan``,
  ``light_gray``, ``dark_gray``, ``light_red``, ``light_green``, ``yellow``,
  ``light_blue``, ``light_purple``, ``light_cyan``, ``white``, ``none``.

  You should probably *not* use the ``black`` colour. Setting affects Bash
  shells *only*. Setting the value to ``none`` uses default terminal colour.

**prompt_id** (string, optional, ``NONE``)
  Optional identifier appended to regular Bash prompt, useful for visually
  identifying distinct environments. For example, if set to ``test``, resulting
  prompt will be similar to ``admin@web[test]:~$``. Setting affects Bash shells
  *only*.


Examples
~~~~~~~~

Here is an example configuration for setting-up some common users, groups, and
packages on all servers:

.. code-block:: yaml

  ---

  os_users:
    - name: admin
      uid: 1000
      additional_groups:
        - sudo
      authorized_keys:
        - "{{ lookup('file', '/home/admin/.ssh/id_rsa.pub') }}"
      password: '$6$AaJRWtqyX5pk$IP8DUjgY0y2zqMom9BAc.O9qHoQWLFCmEsPRCika6l/Xh87cp2SnlMywH0.r4uEcbHnoicQG46V9VrJ8fxp2d.'
    - name: john
      uid: 1001
      password: '$6$AaJRWtqyX5pk$IP8DUjgY0y2zqMom9BAc.O9qHoQWLFCmEsPRCika6l/Xh87cp2SnlMywH0.r4uEcbHnoicQG46V9VrJ8fxp2d.'

  os_groups:
    - name: localusers
      gid: 2500

  common_packages:
    - emacs23-nox
    - screen
    - debconf-utils

  ca_certificates:
    "truststore": "{{ lookup('file', '../certs/truststore.pem') }}"

  incoming_connection_limit: 2/second

  incoming_connection_limit_burst: 6

  prompt_colour: light_green

  prompt_id: PROD

.. _ldap_client:

LDAP Client
-----------

The ``ldap_client`` role can be used for setting-up an OpenLDAP client on
destination machine.

The role implements the following:

* Installs OpenLDAP client tools.
* Sets-up global configuration file for OpenLDAP clients at /etc/ldap/ldap.conf.


Parameters
~~~~~~~~~~

**ldap_client_config** (list, optional, ``[]``)
  A list of configuration options that should be put into the LDAP configuration
  file. Each item is a dictionary with the following options defining the
  configuration parameter:

  **comment** (string, mandatory)
    Comment that will be shown in the file just above the configuration option.

  **option** (string, mandatory)
    Name of configuration option.

  **value** (string, mandatory)
    Value for configuration option.


Examples
~~~~~~~~

Here is an example configuration for setting some common LDAP client options:

.. code-block:: yaml

  ---

  ldap_client_config:
    - comment: Set the base DN
      option: BASE
      value: dc=example,dc=com
    - comment: Set the default URI
      option: URI
      value: ldap://ldap.example.com/
    - comment: Set the truststore for TLS/SSL
      option: TLS_CACERT
      value: /etc/ssl/certs/example_ca.pem
    - commment: Force basic server certificate verification
      option: TLS_REQCERT
      value: demand
    - comment: Disable CRL checks for server certificate
      option: TLS_CRLCHECK
      value: none


LDAP Server
-----------

The ``ldap_server`` role can be used for setting-up an OpenLDAP server on
destination machine.

The role implements the following:

* Deploys LDAP TLS private key and certificate.
* Hardens TLS configuration by allowing only TLSv1.2 and PFS ciphers.
* Installs OpenLDAP server (package ``slapd``).
* Configures OpenLDAP server (base DN - domain, organisation, TLS, SSF, log levels).
* Sets-up separate log file for OpenLDAP server at ``/var/log/slapd.log`` (with
  log rotation included).
* Enables the ``misc`` LDAP schema (from ``/etc/ldap/schema/misc.ldif``). This
  is necessary for the mail server role.
* Enables the ``memberof`` overlay on top of default database. The overlay is
  configured to keep track of membership changes for object class
  ``groupOfUniqueNames`` via attribute ``uniqueMember``. Enforcement of
  referential integrity is turned on as well (modifications of ``memberof``
  attribute will update corresponding group as well.
* Creates a basic directory structure used by most of the other roles.
* Creates a basic directory structure used by the mail server role.
* Creates login entries for services that need to consume LDAP directory data in
  some way.
* Creates user-supplied groups in LDAP.
* Configures permissions.
* Creates LDAP entries.
* Configures firewall to allow incoming connections to the LDAP server (via both
  TCP 389 and 636).
* Sets the LDAP server administrator's password.


LDIF Templates
~~~~~~~~~~~~~~

For adding users, use::

  dn: uid=USERNAME,ou=people,BASE_DN
  objectClass: inetOrgPerson
  objectClass: simpleSecurityObject
  uid: USERNAME
  userPassword: PASSWORD_FROM_SLAPPASSWD
  cn: NAME SURNAME
  sn: SURNAME
  gn: NAME
  displayName: DISPLAYNAME
  initials: INITIALS
  mail: MAIL
  mobile: MOBILE



Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**
* **ldap_client**
* **backup_client**


Backups
~~~~~~~

If the backup for this role has been enabled, the following paths are backed-up:

**/srv/backup/slapd.bak**
  Dump of the LDAP database. LDAP database dump is created every day at 01:45 in
  the morning. This does *not* include the dump of the config database
  (``cn=config``).


Parameters
~~~~~~~~~~

**ldap_admin_password** (string, mandatory)
  Password for the default administrator account of LDAP server (the
  ``cn=admin,DOMAIN`` entry/user).

**ldap_entries** (list, optional, ``[]``)
  List of entries that should be kept in the LDAP directory. Each item is a
  dictionary describing a single LDAP entry, with all of its attributes
  listed. The keys in this dictionary should be the attribute names. The values
  should be either strings, for setting a single attribute value, or a list of
  strings if it is necessary to set multiple values for the same attribute.

**ldap_permissions** (list, optional, ``see below``)
  List of LDAP access rules to apply to base DN served by the LDAP server. The
  listed access control rules will *replace* all existing rules, and will be
  added in the same order they are listed in. Each item is a string that
  constitutes a single access control rule. The format should be the same as
  described in `OpenLDAP Administrator's Guide
  <http://www.openldap.org/doc/admin24/access-control.html#Access%20Control%20via%20Dynamic%20Configuration>`.

  Default value is:

  .. code-block:: yaml

    - >
      to *
      by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
      by * break
    - >
      to attrs=userPassword,shadowLastChange
      by self write
      by anonymous auth
      by dn="cn=admin,BASEDN" write
      by * none
    - >
      to dn.base=""
      by * read
    - >
      to *
      by self write
      by dn="cn=admin,BASEDN" write
      by * none

**ldap_server_consumers** (list, optional, ``[]``)
  List of items describing additional login entries that should be created for
  services that want to be able to log-in into the LDAP server and consume the
  data present within. Each item should be a dictionary, with the following keys
  avaialable:

  - **name** (name of the service, mandatory, this will be used to construct the
    login entry DN in format of ``cn=NAME,ou=services,BASE_DN``)
  - **password** (password for the login entry, mandatory)
  - **state** (state of the service, optional, defaults to ``present``, this
    should be ``present`` or ``absent``, allowing for removal of old services)

**ldap_server_groups** (list, optional, ``[]``)
  List of groups that should be created in the LDAP directory. Each item should
  be a dictionary containing the following keys:

  - **name** (name of the group, mandatory, this will be used to construct the
    group DN in format of ``cn=NAME,ou=groups,BASE_DN``)
  - **state** (state of the group, optional, defaults to ``present``, this
    should be ``present`` or ``absent``, allowing for removal of old groups)

**ldap_server_domain** (string, optional, ``{{ ansible_domain }}``)
  Domain that should be used for constructing the base DN of default user LDAP
  database. This should be a sub-domain dedicated to organisation. The base DN
  will be constructed by putting all elements of the sub-domain as ``dc``
  entries (as per standard Debian convention). I.e. ``example.com`` would get
  transformed into ``dc=example,dc=com``.

**ldap_server_organization** (string, optional, ``Private``)
  Organization that should be specified in the base DN entry.

**ldap_server_log_level** (string, optional, ``256``)
  Log level to use for the server. This should be compatible with OpenLDAP
  configuration option ``olcLogLevel``. See `OpenLDAP Administrator's Guide
  <http://www.openldap.org/doc/admin24/slapdconf2.html#cn=config>` for value
  description and syntax.

**ldap_server_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' ansible_fqdn + '_ldap.pem') }}``)
  X.509 certificate used for TLS for LDAP service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_ldap.pem``.

**ldap_server_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' ansible_fqdn + '_ldap.key') }}``)
  Private key used for TLS for LDAP service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_ldap.key``.

**ldap_server_ssf** (number, optional, ``128``)
  Minimum *Security Strength Factor* to require from all incoming
  connections. This applies for both remote and local connections.


Examples
~~~~~~~~

Here is an example configuration for setting-up LDAP server:

.. code-block:: yaml

  ---

  ldap_server_domain: "example.com"
  ldap_server_organization: "Example Corporation"
  ldap_server_log_level: 256
  ldap_server_tls_certificate: "{{ lookup('file', '~/tls/ldap.example.com_ldap.pem') }}"
  ldap_server_tls_key: "{{ lookup('file', '~/tls/ldap.example.com_ldap.key') }}"
  ldap_server_ssf: 128

  ldap_permissions:
    - >
      to *
      by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
      by * break
    - >
      to attrs=userPassword,shadowLastChange
      by self write
      by anonymous auth
      by dn="cn=admin,dc=example,dc=com" write
      by * none
    - >
      to dn.base=""
      by * read
    - >
      to *
      by self write
      by dn="cn=admin,dc=example,dc=com" write
      by users read
      by * none

  ldap_entries:
    - dn: ou=people,dc=example,dc=com
      objectClass: organizationalUnit
      ou: people
    - dn: ou=groups,dc=example,dc=com
      objectClass: organizationalUnit
      ou: groups
    - dn: uid=john,dc=example,dc=com
      objectClass:
        - inetOrgPerson
        - simpleSecurityObject
      userPassword: somepassword
      uid: john
      cn: John Doe
      sn: Doe


XMPP Server
-----------

The ``xmpp_server`` role can be used for setting-up Prosody, an XMPP server, on
destination machine.

The role implements the following:

* Sets-up the Prosody apt repository.
* Deploys XMPP TLS private key and certificate.
* Installs Prosody.
* Configures Prosody.
* Configures firewall to allow incoming connections to the XMPP server.

Prosody is configured as follows:

* Modules enabled: roster, saslauth, tls, dialback, posix, private, vcard,
  version, uptime, time, ping, pep, register, admin_adhoc, announce, legacyauth.
* Self-registration is not allowed.
* TLS is configured. Legacy TLS is available on port 5223.
* Client-to-server communication requires encryption (TLS).
* Authentication is done via LDAP. For setting the LDAP TLS truststore, see
  :ref:`LDAP Client <ldap_client>`.
* Internal storage is used.
* For each domain specified, a dedicated conference/multi-user chat (MUC)
  service is set-up, with FQDN set to ``conference.DOMAIN``.
* For each domain specified, a dedicated file proxy service will be set-up, with
  FQDN set to ``proxy.DOMAIN``.

.. warning::
   Since it is not possible to set-up separate TLS configuration for *c2s* and
   *s2s* connections in Prosody 0.9.x, no hardening of TLS is performed in order
   to improve interoperability. This will be changed in Prosody 0.10.x, at which
   point hardening can be revisited.

Prosody expects a specific directory structure in LDAP when doing look-ups:

* Prosody will log-in to LDAP as user
  ``cn=prosody,ou=services,XMPP_LDAP_BASE_DN``.
* User entries are read from sub-tree (first-level only)
  ``ou=people,XMPP_LDAP_BASE_DN``. Query filter used for finding users is
  ``(&(mail=$user@$host)(memberOf=cn=xmpp,ou=groups,XMPP_LDAP_BASE_DN))``. This
  allows group-based granting of XMPP service to users.


LDIF Templates
~~~~~~~~~~~~~~

For adding user to a group, use::

  dn: cn=xmpp,ou=groups,BASE_DN
  changetype: modify
  add: uniqueMember
  uniqueMember: uid=USERNAME,ou=people,BASE_DN


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**
* **backup_client**


Backups
~~~~~~~

If the backup for this role has been enabled, the following paths are backed-up:

**/var/lib/prosody/**
  Roster information, as well as undelivered (offline) messages for all XMPP
  users. Keep in mind that list of available users and their credentials are
  stored in the LDAP directory (which is backed-up via LDAP server role).


Parameters
~~~~~~~~~~

**xmpp_administrators** (list, mandatory)
  List of Prosody users that should be granted administrator privileges over
  Prosody. Each item is a string with value equal to XMPP user ID
  (i.e. ``john.doe@example.com``).

**xmpp_domains** (list, optional, ``{{ ansible_domain }}``)
  List of domains that are served by this Prosody instance. Each item is a
  string specifying a domain.

**xmpp_ldap_base_dn** (string, mandatory)
  Base DN on the LDAP server. A specific directory structure is expected under
  this entry (as explained above) in order to locate the available domains,
  users, aliases etc.

**xmpp_ldap_password** (string, mandatory)
  Password used for authenticating to the LDAP server.

**xmpp_ldap_server** (string, mandatory)
  Fully qualified domain name, hostname, or IP address of the LDAP server used
  for user authentication and listing.

**xmpp_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' + fqdn + '_xmpp.pem') }}``)
  X.509 certificate used for TLS for XMPP service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_xmpp.pem``.

**xmpp_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' + fqdn + '_xmpp.key') }}``)
  Private key used for TLS for XMPP service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_xmpp.key``.


Examples
~~~~~~~~

Here is an example configuration for setting-up XMPP server using Prosody:

.. code-block:: yaml

  ---

  xmpp_administrators:
    - john.doe@example.com
  xmpp_domains:
    - example.com
  xmpp_ldap_base_dn: dc=example,dc=com
  xmpp_ldap_password: xmpp
  xmpp_ldap_server: ldap.example.com
  # These are default key and certificate that generated during Prosody
  # installation. Possibly you want to deploy your own.
  xmpp_tls_key: "{{ lookup('file', '/etc/prosody/certs/localhost.key') }}"
  xmpp_tls_certificate: "{{ lookup('file', '/etc/prosody/certs/localhost.crt') }}"


Mail Server
-----------

.. warning::
   It may happen that the ``clamav-freshclam`` service hasn't finished
   downloading the virus database before the ``clamav-daemon`` and
   ``clamav-milter`` services are enabled during the initial run. If mail server
   is not operational, you may need to wait for a little while for download to
   finish, and then restart the ``clamav-daemon`` and ``clamav-milter``
   services.

The ``mail_server`` role can be used for setting-up a complete mail server
solution, which includes both SMTP and IMAP service, on destination machine.

Postfix is used SMTP, while Dovecot is used for IMAP.

The role implements the following:

* Installs rsync.
* Deploys IMAP/SMTP TLS private keys and certificates.
* Installs and configures Dovecot, Postfix, ClamAV, and ClamAV Milter.
* Purges Exim4 configuration (just in case).
* Installs SWAKS (utility for testing SMTP servers).
* Sets-up the necessary directories and files under Postfix chroot.
* Configures firewall to allow incoming connections to the mail server. This
  includes set-up of redirection from TCP port 26 to TCP port 587 (alternate
  SMTP submission port to work around common network blocks).

Deployed services are configured as follows:

* Both Postfix and Dovecot look-up available domains, users, and aliases in
  LDAP.
* Incoming and outgoing mail is scanned with ClamAV (via ClamAV
  Milter). Infected mails are rejected.
* Mail is stored in directory ``/var/MAIL_USER/DOMAIN/USER``, using ``Maildir``
  format.
* TLS is required for user log-ins for both SMTP and IMAP.
* For user submission (SMTP), users must connect and authenticate over TCP
  port 587.
* TLS configuration is hardened for Dovecot, allowing only TLSv1.2 and PFS
  ciphers.
* TLS configuration is hardened for Postfix on submission port 587, allowing
  only TLSv1.2 and PFS ciphers. No TLS hardening is performed on port 25 in
  order to maintain maximum interoperability.
* RBL's are used for combating spam (if any is specified in configuration, see
  below).

Both Postfix and Dovecot expect a specific directory structure in LDAP when
doing look-ups:

* Postfix will log-in to LDAP as user
  ``cn=postfix,ou=services,MAIL_LDAP_BASE_DN``.
* Dovecot will log-in to LDAP as user
  ``cn=dovecot,ou=services,MAIL_LDAP_BASE_DN``.
* Domain entries need to be available as
  ``dc=DOMAIN,ou=domains,ou=mail,ou=services,MAIL_LDAP_BASE_DN``.
* Alias entries need to be available as
  ``cn=ALIAS,ou=aliases,ou=mail,ou=services,MAIL_LDAP_BASE_DN``.
* User entries are read from sub-tree (first-level only)
  ``ou=people,MAIL_LDAP_BASE_DN``. Query filter used for finding users is
  ``(&(mail=%s)(memberOf=cn=mail,ou=groups,MAIL_LDAP_BASE_DN))``. This allows
  group-based granting of mail services to users.


LDIF Templates
~~~~~~~~~~~~~~

For adding domains, use::

  dn: dc=DOMAIN,ou=domains,ou=mail,ou=services,BASE_DN
  objectClass: dNSDomain
  dc: DOMAIN

For adding aliases, use::

  dn: cn=ALIAS,ou=aliases,ou=mail,ou=services,BASE_DN
  objectClass: nisMailAlias
  cn: ALIAS
  rfc822MailMember: REALEMAIL

For adding user to a group, use::

  dn: cn=mail,ou=groups,BASE_DN
  changetype: modify
  add: uniqueMember
  uniqueMember: uid=USERNAME,ou=people,BASE_DN


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**
* **backup_client**


Backups
~~~~~~~

If the backup for this role has been enabled, the following paths are backed-up:

**/var/{{ mail_user }}**
  All data stored by the mail server, including mails and Sieve scripts. Keep in
  mind that list of available users and their credentials are stored in the LDAP
  directory (which is backed-up via LDAP server role).


Parameters
~~~~~~~~~~

**mail_ldap_base_dn** (string, mandatory)
  Base DN on the LDAP server. A specific directory structure is expected under
  this entry (as explained above) in order to locate the available domains,
  users, aliases etc.

**mail_ldap_url** (string, mandatory)
  LDAP URL that should be used for connecting to the LDAP server for doing
  domain/user look-ups.

**mail_ldap_tls_truststore** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/truststore.pem') }}``)
  X.509 certificate chain used for issuing certificate for the LDAP service. The
  file will be stored in locations ``/etc/ssl/certs/mail_ldap_tls_truststore.pem``
  and ``/var/spool/postfix/etc/ssl/certs/mail_ldap_tls_truststore.pem``.

**mail_ldap_postfix_password** (string, mandatory)
  Password for authenticating the Postfix LDAP user.

**mail_ldap_dovecot_password** (string, mandatory)
  Password for authenticating the Dovecot LDAP user.

**mail_user** (string, optional, ``vmail``)
  Name of the user that owns all the mail files.

**mail_user_uid** (integer, optional, ``whatever OS picks``)
  UID of the user that owns all the mail files.

**mail_user_gid** (integer, optional, ``whatever OS picks``)
  GID of the user that owns all the mail files.

**imap_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' ansible_fqdn + '_imap.pem') }}``)
  X.509 certificate used for TLS for IMAP service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_imap.pem``.

**imap_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' ansible_fqdn + '_imap.key') }}``)
  Private key used for TLS for IMAP service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_imap.key``.

**smtp_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' ansible_fqdn + '_smtp.pem') }}``)
  X.509 certificate used for TLS for SMTP service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_smtp.pem``.

**smtp_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' ansible_fqdn + '_smtp.key') }}``)
  Private key used for TLS for SMTP service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_smtp.key``.

**imap_folder_separator** (string, optional, ``/``)
  Character used for separating the IMAP folders when clients are requesting
  listing from the server. Usually either slash(``/``) or dot(``.``).

**smtp_rbl** (list, optional, ``[]``)
  List of RBLs to use for detecting servers which send out spam. Each item is a
  string resembling the RBL domain.

**mail_postmaster** (string, optional, ``postmaster@{{ ansible_domain}}``)
  Mail address to use for the postmaster account in Dovecot.

**smtp_allow_relay_from** (list, optional, [])
  List of networks from which mail relaying is allowed even without
  authentication. Each item in the list is a string defining a network. The
  format must be compatible with Postfix ``mynetworks`` setting (for example:
  ``192.168.1.0/24``, ``myhost.example.com`` etc).


Examples
~~~~~~~~

Here is an example configuration for setting-up XMPP server using Prosody:

.. code-block:: yaml

  ---

  mail_ldap_url: ldap://ldap.example.com/
  mail_ldap_tls_truststore: /etc/ssl/certs/truststore.pem
  mail_ldap_base_dn: dc=example,dc=com
  mail_ldap_postfix_password: postfix
  mail_ldap_dovecot_password: dovecot

  mail_user: vmail
  mail_user_uid: 5000
  mail_user_gid: 5000

  imap_tls_certificate: "{{ lookup('file', '~/tls/mail.example.com_imap.pem') }}"
  imap_tls_key: "{{ lookup('file', '~/tls/mail.example.com_imap.key') }}"
  smtp_tls_certificate: "{{ lookup('file', '~/tls/mail.example.com_smtp.pem') }}"
  smtp_tls_key: "{{ lookup('file', '~/tls/mail.example.com_smtp.key') }}"
  imap_folder_separator: /
  smtp_rbl:
    - bl.spamcop.net
    - zen.spamhaus.org
  mail_postmaster: postmaster@example.com

  smtp_allow_relay_from:
    - ldap.example.com
    - xmpp.example.com


Mail Forwarder
--------------

The ``mail_forwarder`` role can be used for setting-up a local SMTP server for
sending out mails and receiving mails for local users. The SMTP server is
provided by Postfix.

SMTP service on server set-up this way is not meant to be exposed to the
Internet directly, and should receive delivery failures from the relay server
instead.

The role implements the following:

* Installs and configures Postfix.
* Purges Exim4 configuration (just in case).
* Sets-up aliases for the local recipients.
* Installs SWAKS (utility for testing SMTP servers).

Postfix is configured as follows:

* Local destinations are set-up.
* A relay host is set.
* TLS is enforced for relaying mails, with configurable truststore for server
  certificate verification.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**


Parameters
~~~~~~~~~~

**local_mail_aliases** (dictionary, optional, ``[]``)
  Dictionary defining the local aliases. Aliases defined this way will either be
  appended to default aliases on the server, or replace the existing entries (if
  the alias/recipient is already present). Keys in the dictionary are the local
  recipients/aliases, while the value provided should be a space-separated list
  of mail addresses (or local users) where the mails should be forwarded.

**smtp_relay_host** (string, optional, ``None``)
  SMTP server via which the mails are sent out for non-local recipients.

**smtp_relay_truststore** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/truststore.pem') }}``)
  X.509 certificate chain used for issuing certificate for the SMTP relay
  service. The file will be stored in location
  ``/etc/ssl/certs/smtp_relay_truststore.pem``


Examples
~~~~~~~~

Here is an example configuration for setting-up the mail forwarder:

.. code-block:: yaml

  ---

  # All mails sent to local user root will be forwarded to external account as
  # well.
  local_mail_aliases:
    root: "root john.doe@example.com"

  smtp_relay_host: mail.example.com

  smtp_relay_truststore: /etc/ssl/certs/example_ca_chain.pem


Web Server
----------

The ``web_server`` role can be used for setting-up a web server on destination
machine.

The role is supposed to be very lightweight, providing a basis for deployment of
web applications.

The role implements the following:

* Installs and configures nginx with a single, default vhost with a small static
  index page.
* Deploys the HTTPS TLS private key and certificate (for default vhost).
* Hardens TLS configuration by allowing only TLSv1.2 and PFS ciphers.
* Configures firewall to allow incoming connections to the web server.
* Installs and configures virtualenv and virtualenvwrapper as a common base for
  Python apps.
* Installs and configures PHP FPM as a common base for PHP apps.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**


Parameters
~~~~~~~~~~

**default_enforce_https** (boolean, optional, ``True``)
  Specify if HTTPS should be enforced for the default virtual host or not. If
  enforced, clients connecting via plaintext will be redirected to HTTPS.

**default_https_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' + ansible_fqdn + '_https.pem') }}``)
  X.509 certificate used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_https.pem``.

**default_https_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' + ansible_fqdn + '_https.key') }}``)
  Private key used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_https.key``.

**web_default_title** (string, optional, ``Welcome``)
  Title for the default web page shown to users (if no other vhosts were matched).

**web_default_message** (string, optional, ``You are attempting to access the web server using a wrong name or an IP address. Please check your URL.``)
  Message for the default web page shown to users (if no other vhosts were
  matched).


Examples
~~~~~~~~

Here is an example configuration for setting-up web server:

.. code-block:: yaml

  ---

  default_https_tls_key: "{{ lookup('file', inventory_dir + '/tls/web.example.com_https.key') }}"
  default_https_tls_certificate: "{{ lookup('file', inventory_dir + '/tls/web.example.com_https.pem') }}"

  web_default_title: "Welcome to Example Inc."
  web_default_message: "You are attempting to access the web server using a wrong name or an IP address. Please check your URL."


PHP Website
-----------

The ``php_website`` role can be used for setting-up a website powered by PHP on
destination machine.

This role is normally not supposed to be used directly, but should instead serve
as the basis for writing website-specific roles. Therefore the role is written
in quite generic way, allowing the integrator to write his/her own logic for
deploying the necessary PHP applications, while still reusing a common base and
reducing the workload.

The role implements the following:

* Creates a dedicated user/group for running the PHP scripts.
* Creates a dedicated administrator user for maintaining the website.
* Creates a base directory where the website-specific code and data should be
  stored at.
* Adds nginx to website's group, so nginx could read the necessary files.
* Adds website administrator to website's group, so administrator could manage
  the code and data.
* Installs additional packages required for running the role (as configured).
* Deploys the HTTPS TLS private key and certificate (for website vhost).
* Configures PHP FPM and nginx to serve the website.

The role is implemented with the following layout/logic in mind:

* Website users are named after the ``FQDN`` (fully qualified domain name) of
  website, in format of ``web-ESCAPEDFQDN``, where ``ESCAPEDFQDN`` is equal to
  ``FQDN`` where dots have been replaced by underscores (for example,
  ``web-cloud_example_com``).
* Administrator users are named after the ``FQDN`` (fully qualified domain name)
  of website, in format of ``admin-ESCAPEDFQDN``, where ``ESCAPEDFQDN`` is equal
  to ``FQDN`` where dots have been replaced by underscores (for example,
  ``admin-cloud_example_com``).
* All websites reside within a dedicated sub-directory in ``/var/www``. The
  sub-directory name is equal to the ``FQDN`` used for accessing the
  website. Owner of the directory is set to be the application administrator,
  while group is set to be the website group. Additionally, ``SGID`` bit is set
  on the directory. This allows admin, with correct umask, to create necessary
  files and directories that should be readable (and eventually writeable) by
  the website user (running the PHP scripts) without having to become root.
* All files placed in the website directory should be either created there
  directly, or copied to the directory in order to make sure the ``SGID`` gets
  honored. **Do not move the files, the permissions will not be set correctly.**
* Within the website directory, nginx/php5-fpm will expect to find the relevant
  files within the htdocs sub-directory (this can be symlink too).
* nginx communicates with PHP FPM over a dedicated Unix socket for each website.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**
* **web_server**


Parameters
~~~~~~~~~~

**additional_nginx_config** (list, optional, ``[]``)
  List providing additional Nginx configuration options to include. This can be
  useful for specifying things like error pages. Options are applied inside of a
  **server** context of Nginx configuration file.

  Each item is a dictionary with the following options describing the extra
  configuration option:

  **comment** (string, mandatory)
    Comment describing the configuration option.

  **value** (string, mandatory)
    Configuration option.

**admin_uid** (integer, optional, ``whatever OS picks``)
  UID of the dedicated website administrator user. The user will be member of
  website group.

**deny_files_regex** (list, optional, ``[]``)
  List of regular expressions for matching files/locations to which the web
  server should deny access. This is useful to block access to any sensitive
  files that should not be served directly by the web server. The format must be
  compatible with regular expressions used by ``nginx`` for ``location ~``
  syntax.

**enforce_https** (boolean, optional, ``True``)
  Specify if HTTPS should be enforced for the website or not. If enforced,
  clients connecting via plaintext will be redirected to HTTPS.

**fqdn** (string, mandatory)
  Fully-qualified domain name where the website is reachable. This value is used
  for calculating the user/group name for dedicated website user, as well as
  home directory of the website user (where data/code should be stored at).

**index** (string, optional, ``index.php``)
  Space-separated list of files which should be treated as index files by the
  web server. The web server will attempt opening these index files, in
  succession, until the first match, or until it runs out of matches, when a
  client requests an URI pointing to directory.

**https_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' + fqdn + '_https.pem') }}``)
  X.509 certificate used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ fqdn }}_https.pem``.

**https_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' + fqdn + '_https.key') }}``)
  Private key used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ fqdn }}_https.key``.

**php_file_regex** (string, optional, ``\.php$``)
  Regular expression used for determining which file should be interepted via
  PHP.

**php_rewrite_urls** (list, optional, ``[]``)
  A list of rewrite rules that are applied to incoming requests. These rewrite
  rules are specifically targetted at prettying-up the URLs used by the PHP
  scripts. Each element of the list should be a string value compatible with the
  format of ``nginx`` option ``rewrite``. The keyword ``rewrite`` itself should
  be omitted, as well as trailing semi-colon (``;``).

**rewrites** (list, optional, ``[]``)
  A list of rewrite rules that are applied to incoming requests. Each element of
  the list should be a string value compatible with the format of ``nginx``
  option ``rewrite``. The keyword ``rewrite`` itself should be omitted, as well
  as trailing semi-colon (``;``).

**packages** (list, optional, ``[]``)
  A list of additional packages to install for this particular PHP
  appliction. This is usually going to be different PHP extensions.

**uid** (integer, optional, ``whatever OS picks``)
  UID/GID (they are set-up to be the same) of the dedicated website
  user/group.


Examples
~~~~~~~~

Here is an example configuration for setting-up two (base) PHP websites (for
running *ownCloud* and *The Bug Genie* applications):

.. code-block:: yaml

    - role: php_website
      fqdn: cloud.example.com
      uid: 2001
      php_file_regex: \.php($|/)
      rewrites:
        - ^/\.well-known/host-meta /public.php?service=host-meta
        - ^/\.well-known/host-meta\.json /public.php?service=host-meta-json
        - ^/\.well-known/carddav /remote.php/carddav/ redirect
        - ^/\.well-known/caldav /remote.php/caldav/ redirect
        - ^/apps/calendar/caldav\.php /remote.php/caldav/
        - ^/apps/contacts/carddav\.php /remote.php/carddav/
        - ^/remote/(.*) /remote.php
      deny_files_regex:
        - ^(\.|autotest|occ|issue|indie|db_|console|build/|tests/|config/|lib/|3rdparty/|templates/).*
      packages:
        # For ownCloud
        - php5-gd
        - php5-json
        - php5-mysql
        - php5-curl
      https_tls_key: "{{ lookup('file', inventory_dir + '/tls/cloud.example.com_https.key') }}"
      https_tls_certificate: "{{ lookup('file', inventory_dir + '/tls/cloud.example.com_https.pem') }}"
      additional_nginx_config:
        - comment: Use custom page for forbidden files.
          value: error_page 403 /core/templates/403.php;
        - comment: Use custom page for non-existing locations/files.
          value: error_page 404 /core/templates/404.php;
    - role: php_website
      deny_files_regex:
        - ^\..*
      php_rewrite_urls:
        - ^(.*) /index.php?url=$1
      fqdn: tbg.example.com
      uid: 2007
      https_tls_key: "{{ lookup('file', inventory_dir + '/tls/tbg.example.com_https.key') }}"
      https_tls_certificate: "{{ lookup('file', inventory_dir + '/tls/tbg.example.com_https.pem') }}"


WSGI Website
------------

The ``wsgi_website`` role can be used for setting-up a website powered by Python
on destination machine. The website needs to use the WSGI specification for
making the Python web application(s) available.

This role is normally not supposed to be used directly, but should instead serve
as the basis for writing website-specific roles. Therefore the role is written
in quite generic way, allowing the integrator to write his/her own logic for
deploying the necessary Python applications/packages, while still reusing a
common base and reducing the workload.

The role implements the following:

* Creates a dedicated user/group for running the WSGI application.
* Creates a dedicated administrator user for maintaining the website.
* Creates a base directory where the website-specific code and data should be
  stored at.
* Adds nginx to website's group, so nginx could read the necessary files.
* Adds website administrator to website's group, so administrator could manage
  the code and data.
* Installs additional packages required for running the role (as configured).
* Sets-up a dedicated Python virtual environment for website.
* Install ``futures`` package in Python virtual environment (required for
  Gunicorn in combination withg Python 2.7).
* Install Gunicorn in Python virtual environment.
* Installs additional packages required for running the role in Python virtual
  environment (as configured).
* Configures systemd to run the website code (using Gunicorn)
* Deploys the HTTPS TLS private key and certificate (for website vhost).
* Configures nginx to serve the website (static files served directly, requests
  passed on to Gunicorn).

The role is implemented with the following layout/logic in mind:

* Website users are named after the ``FQDN`` (fully qualified domain name) of
  website, in format of ``web-ESCAPEDFQDN``, where ``ESCAPEDFQDN`` is equal to
  ``FQDN`` where dots have been replaced by underscores (for example,
  ``web-wiki_example_com``).
* Administrator users are named after the ``FQDN`` (fully qualified domain name)
  of website, in format of ``admin-ESCAPEDFQDN``, where ``ESCAPEDFQDN`` is equal
  to ``FQDN`` where dots have been replaced by underscores (for example,
  ``admin-cloud_example_com``).
* All websites reside within a dedicated sub-directory in ``/var/www``. The
  sub-directory name is equal to the ``FQDN`` used for accessing the
  website. Owner of the directory is set to be the application administrator,
  while group is set to be the website group. Additionally, ``SGID`` bit is set
  on the directory. This allows admin, with correct umask, to create necessary
  files and directories that should be readable (and eventually writeable) by
  the website user (running the WSGI application) without having to become root.
* All files placed in the website directory should be either created there
  directly, or copied to the directory in order to make sure the ``SGID`` gets
  honored. **Do not move the files, the permissions will not be set correctly.**
* Within the website directory, Python virtual environment can be found within
  the ``virtualenv`` sub-directory. Switching to administrator user via login
  shell will automatically activate the virtual environment.
* Within the website directory, nginx will expect to find the static files
  within the ``htdocs`` sub-directory (this can be symlink too). Locations/aliases
  can be configured for static file serving.
* Within the website directory, systemd service will expect to find the website
  code within the ``code`` sub-directory (this can be symlink too).
* nginx communicates with WSGI server over a dedicated Unix socket for each
  website.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**
* **web_server**


Parameters
~~~~~~~~~~

**additional_nginx_config** (list, optional, ``[]``)
  List providing additional Nginx configuration options to include. This can be
  useful for specifying things like error pages. Options are applied inside of a
  **server** context of Nginx configuration file.

  Each item is a dictionary with the following options describing the extra
  configuration option:

  **comment** (string, mandatory)
    Comment describing the configuration option.

  **value** (string, mandatory)
    Configuration option.

**admin_uid** (integer, optional, ``whatever OS picks``)
  UID of the dedicated website administrator user. The user will be member of
  website group.

**enforce_https** (boolean, optional, ``True``)
  Specify if HTTPS should be enforced for the website or not. If enforced,
  clients connecting via plaintext will be redirected to HTTPS.

**fqdn** (string, mandatory)
  Fully-qualified domain name where the website is reachable. This value is used
  for calculating the user/group name for dedicated website user, as well as
  home directory of the website user (where data/code should be stored at).

**futures_version** (string, optional, ``3.0.5``)
  Version of ``futures`` package to deploy in virtual environment. Required by
  Gunicorn when using Python 2.7. Default version is tested with the test site.

**gunicorn_version** (string, optional, ``19.6.0``)
  Version of Gunicorn to deploy in virtual environment for running the WSGI
  application. Default version is tested with the test site.

**https_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' + fqdn + '_https.pem') }}``)
  X.509 certificate used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/certs/`` under name ``{{ fqdn }}_https.pem``.

**https_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' + fqdn + '_https.key') }}``)
  Private key used for TLS for HTTPS service. The file will be stored in
  directory ``/etc/ssl/private/`` under name ``{{ fqdn }}_https.key``.

**packages** (list, optional, ``[]``)
  A list of additional packages to install for this particular WSGI
  website. This is usually going to be development libraries for building Python
  packages.

**rewrites** (list, optional, ``[]``)
  A list of rewrite rules that are applied to incoming requests. Each element of
  the list should be a string value compatible with the format of ``nginx``
  option ``rewrite``. The keyword ``rewrite`` itself should be omitted, as well
  as trailing semi-colon (``;``).

**static_locations** (list, optional, ``[]``)
  List of locations that should be treated as static-only, and not processed by
  the WSGI application at all. This is normally used for designating serving of
  static/media files by Nginx (for example, in case of Django projects for
  ``/static/`` and ``/media/``).

**uid** (integer, optional, ``whatever OS picks``)
  UID/GID (they are set-up to be the same) of the dedicated website
  user/group.

**use_paste** (boolean, optional, ``False``)
  Tell Gunicorn to assume that the passed-in ``wsgi_application`` value is a
  filename of a Python Paste ``ini`` file instead of WSGI application.

**virtuaelnv_packages** (list, optional, ``[]``)
  A list of additional packages to install for this particular WSGI appliction
  in its virtual environment using ``pip``.

**wsgi_application** (string, mandatory)
  WSGI application that should be started by Gunicorn. The format should be
  conformant to what the ``gunicorn`` command-line tool accepts. If the
  ``use_paste`` option is enabled, the value should be equal to filename of the
  Python Paste ini file, located in the ``code`` sub-directory. It should be
  noted that in either case the value should be specsified relative to the
  ``code`` sub-directory. I.e. don't use full paths.


Examples
~~~~~~~~

Here is an example configuration for setting-up a (base) WSGI website (for
running a bare Django project):

.. code-block:: yaml

    - role: wsgi_website
      fqdn: django.example.com
      static_locations:
        - /static
        - /media
      uid: 2004
      virtualenv_packages:
        - django
      wsgi_application: django_example_com.wsgi:application
      https_tls_key: "{{ lookup('file', inventory_dir + '/tls/wsgi.example.com_https.key') }}"
      https_tls_certificate: "{{ lookup('file', inventory_dir + '/tls/wsgi.example.com_https.pem') }}"
      futures_version: 3.0.5
      gunicorn_version: 19.6.0
      additional_nginx_config:
        - comment: Use custom page for forbidden files.
          value: error_page 403 /static/403.html;
        - comment: Use custom page for non-existing locations/files.
          value: error_page 404 /static/404.html;


Database Server
---------------

The ``database_server`` role can be used for setting-up a MariaDB database
server on destination machine.

The role implements the following:

* Installs MariaDB server and client.
* Configures MariaDB server and client to use *UTF-8* encoding by default.
* Sets password for the database root user.
* Deploys MariaDB client configuration in location ``/root/.my.cnf`` that
  contains username and password for the root database user.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**


Parameters
~~~~~~~~~~

**db_root_password** (string, mandatory)
  Password for the *root* database user.


Examples
~~~~~~~~

Here is an example configuration for setting-up the database server:

.. code-block:: yaml

   ---

   db_root_password: root


Database
--------

The ``database`` role can be used for creating a MariaDB database and
accompanying user on destination machine.

The role implements the following:

* Creates MariaDB database.
* Creates a dedicated user capable of performing any operation on the created
  database. Username is set to be same as the name of database.
* Sets-up pre-backup task that creates database dump in location
  ``/srv/backup/mariadb/{{ db_name }}.sql``.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **database_server**
* **backup_client**


Backups
~~~~~~~

If the backup for this role has been enabled, the following paths are backed-up:

**/srv/backup/maraidb/{{ db_name }}.sql**
  Dump of the database. Database dump is created every day at 01:45 in the
  morning.


Parameters
~~~~~~~~~~

**db_name** (string, mandatory)
  Name of the database that should be created.

**db_password** (string, mandatory)
  Password for the database user.


Examples
~~~~~~~~

Here is an example configuration for creating a single database (for some
website):

.. code-block:: yaml

  - role: database
    db_name: phpinfo_example_com
    db_password: phpinfo_example_com


Backup Server
-------------

The ``backup_server`` role can be used for setting-up a server to act as backup
storage for the backup clients. Storage is made available to the clients
exclusively via SFTP on a dedicated port and dedicated OpenSSH server
instance. This instance is specifically configured and tailored for this
purpose.

The role is primarily aimed for use with `Duplicity
<http://duplicity.nongnu.org/>`_, but should be also usable for generic SFTP
uploads.

The role implements the following:

* Installs backup software (Duplicity, Duply).
* Creates a dedicated directory structure for backups with the following structure:

  * ``/srv/backups/`` - main directory under which all the backups reside.
  * ``/srv/backups/SERVER_NAME/`` - home directory for the backup user, name
    after the server. Backup users are confined to their respective home
    directory via chroot. Backup users can't write to their own home directory,
    though.
  * ``/srv/backups/SERVER_NAME/duplicity/`` - directory where the Duplicity
    backups are stored at. This directory is writable by the respective backup
    user.
  * ``SERVER_NAME/.ssh/`` - directory where authorized keys are stored. Backup
    user is not allowed to make modifications to this directory and files
    contained within (i.e. backup users can't add more keys to the
    ``authorized_keys`` file).
* Creates dedicated operating system users for backup clients. These users will
  be made members of the ``backup`` group as well (as an additional group).
* Sets-up ``authorized_keys`` for the backup clients.
* Makes sure the backup users can't log-in via regular OpenSSH server instance.
* Sets-up dedicated OpenSSH server instances to be used exclusively by backup
  clients. The instance listens on TCP port ``2222``.
* Updates firewall to allow incoming TCP connections to port
  ``2222``. Connections are allowed only from the configured IP addresses
  associated with backup clients.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **common**


Parameters
~~~~~~~~~~

**backup_clients** (list, optional)
  List of backup clients that are connecting to the backup server. This is
  usually done on a per-server basis. Each item in the list is a dictionary
  describing the backup client. The following keys are available:

  **server** (string, mandatory)
    Name of the server that is backed up. It is highly recommended to use
    server's FQDN for this purpose. The dedicated operating system user created
    will have the name of format ``bak-ESCAPED_SERVER_NAME``, where
    ``ESCAPED_SERVER_NAME`` is calculated by taking the passed-in server name
    and replacing all dots (``.``) with undescores (``_``). For example,
    ``web.example.com`` will be turned into ``bak-web_example_com``.

  **uid** (integer, optional, ``whatever OS picks``)
    Uid for the operating system user. User's default group will have a GID
    identical to the user's UID if specified. Otherwise user's default group
    will have OS-determined GID.

  **ip** (IPv4 address, mandatory)
    IPv4 address from which the backup client server is connecting to the backup
    server. Used for introducing stricter firewall rules.

  **public_key** (string, mandatory)
    SSH public key used by backup client to connect to the backup server.

**backup_host_ssh_private_keys** (dictionary, mandatory)
  Defines host keys used for the dedicated OpenSSH server instance for
  backup. Key values that must be provided are: **dsa**, **rsa**, **ed25519**,
  and **ecdsa**, with values for each one of them corresponding to a private key
  generated using the appropriate algorithm. Keys for this purpose can be easily
  created via commands::

    ssh-keygen -f backup_server_dsa_key -N '' -t dsa
    ssh-keygen -f backup_server_rsa_key -N '' -t rsa
    ssh-keygen -f backup_server_ed25519_key -N '' -t ed25519
    ssh-keygen -f backup_server_ecdsa_key -N '' -t ecdsa


Examples
~~~~~~~~

Here is an example configuration for setting-up the backup server role:

.. code-block:: yaml

  - role: backup_server
    backup_clients:
      - server: web.example.com
        uid: 3000
        public_key: "{{ lookup('file', inventory_dir + '/ssh/web.example.com.pub') }}"
        ip: 10.32.64.18
      - server: mail.example.com
        public_key: "{{ lookup('file', inventory_dir + '/ssh/mail.example.com.pub') }}"
        ip: 10.32.64.15
    backup_host_ssh_private_keys:
      dsa: "{{ lookup('file', inventory_dir + '/ssh/backup_server_dsa_key') }}"
      rsa: "{{ lookup('file', inventory_dir + '/ssh/backup_server_rsa_key') }}"
      ed25519: "{{ lookup('file', inventory_dir + '/ssh/backup_server_ed25519_key') }}"
      ecdsa: "{{ lookup('file', inventory_dir + '/ssh/backup_server_ecdsa_key') }}"


Backup Client
-------------

The ``backup_client`` role can be used for setting-up the server as a backup
client so it can perform backups to the backup server.

Backup clients utilise duplicity (via the duply convenience wrapper) for
performing the backups to a backup server via *SFTP* protocol.

The role itself will take care of deploying the necessary software,
configuration files, and encryption/signing private key to the backup client in
order to be able to perform backup.

Files that should be backed-up are specified using the ``backup`` role.

The role implements the following:

* Installs backup software (Duplicity, Duply).
* Sets-up Duply configuration under directory ``/etc/duply/main/``.
* Deploys encryption/signing private key (usually host-specific), as well as
  additional encryption public keys to the server, and imports them into local
  GnuPG keyring used by backup software.
* Deploys private SSH key for logging-in into the backup server over SFTP.
* Deploys ``known_hosts`` file for SFTP fingerprint verification.
* Sets-up a handler that runs scripts/binaries before the actual backup
  run. This is helpful for producing database backups. Such scripts/binaries
  should be deployed to directory ``/etc/duply/main/pre.d/``, and marked
  executable by the root user.

Duply is configured as follows:

* GnuPG keyring is stored under ``/etc/duply/main/gnupg/``. The keyring should
  not be managed manually.
* SSH private key for logging-in into backup server is stored in location
  ``/etc/duply/main/ssh/identity``. Backup server SFTP fingerprint is stored in
  location ``/etc/duply/main/ssh/known_hosts``.
* Base directory for back-ups is root (``/``), but *all* files are excluded by
  default to prevent huge back-ups. Ansible roles that want to utilise the
  backup client role can specify which patterns should be included in the backup
  when including the ``backup`` role. Include pattern file is assembled and
  stored in location ``/etc/duply/main/include``.
* Backups are encrypted and signed with the specified encryption key.
* Maximum age for old backups is set to 6 months.
* Maximum age for full backups is set to 1 month.
* Volume size is set to 1GB.
* Pre-backup scripts are run via ``/etc/duply/main/pre`` handler that tries to
  execute scripts/binaries from directory ``/etc/duply/main/pre.d/``.

.. note::
   Since at time of this writing there are no lookup plugins for extracting key
   material/information from GnuPG keyring, you may want to resort to extraction
   of keys on the controller machine via lookups similar to::

     lookup('pipe', 'gpg2 --homedir /path/to/your/keyring --armor --export some_identifier')
     lookup('pipe', 'gpg2 --homedir /path/to/your/keyring --armor --export-secret-keys some_identifier')

   This may not be the most elegant solution, but for now it offers better
   flexibility (theoretically, you could store all those keys etc as plaintext
   files instead).


Parameters
~~~~~~~~~~

**backup_additional_encryption_keys** (list, optional, ``[]``)
  List of additional public encryption keys used for backup operation. Each item
  in the list should be an ASCII armour-encoded public key exported from a GnuPG
  keyring. These additional public keys are useful in cases where the backups
  should be decryptable with some master key in addition to server-specific key.

**backup_client_username** (string, optional, ``bak-{{ ansible_fqdn | replace('.', '_') }}``)
  Username for connecting to the backup server via SFTP.

**backup_encryption_key** (string, mandatory)
  Private GnuPG key, encoded using ASCII armor, used for encryption and signing
  operations when running the backup on the client server. This *must* be a
  private key! This is normally host-specific encryption key that is distributed
  to destination server and that can be also used for the restore operations
  (for data decryption). The key must not be password-protected.

**backup_server** (string, mandatory)
  Backup server to connect to.

**backup_server_destination** (string, optional, ``//duplicity``)
  Target directory on the backup server where the backups are stored.

**backup_server_host_ssh_public_keys** (list, mandatory)
  SSH public keys presented by the server during client authentication. These
  public keys are used for populating the known hosts on the backup client side
  for host verification purposes.

**backup_server_port** (int, optional, ``2222``)
  Port on the backup server to connect to for accessing the SFTP service.

**backup_ssh_key** (string, mandatory)
  SSH private key for logging-in into the backup server.


Examples
~~~~~~~~

Here is an example configuration for setting-up the role (take note that lookup
plugin is quite useful here for fetching key values from some local directory):

.. code-block:: yaml

  - role: backup_client
    backup_additional_encryption_keys: "-----BEGIN PGP PUBLIC KEY BLOCK-----\n...\n-----END PGP PUBLIC KEY BLOCK-----"
    backup_client_username: "user"
    backup_encryption_key: "-----BEGIN PGP PRIVATE KEY BLOCK-----\n...\n-----END PGP PRIVATE KEY BLOCK-----"
    backup_server: "backup.example.com"
    backup_server_destination: "//example/host"
    backup_server_host_ssh_public_keys:
      - "{{ lookup('file', inventory_dir + '/ssh/backup_server_dsa_key.pub') }}"
      - "{{ lookup('file', inventory_dir + '/ssh/backup_server_ecdsa_key.pub') }}"
      - "{{ lookup('file', inventory_dir + '/ssh/backup_server_ed25519_key.pub') }}"
      - "{{ lookup('file', inventory_dir + '/ssh/backup_server_rsa_key.pub') }}"
    backup_server_port: 22
    backup_ssh_key: "{{ lookup('file', inventory_dir + '/ssh/web.example.com') }}"


Backup
------

The ``backup`` role can be used to specify what files should be backed-up to the
backup server.

The role provides a convenient way to deploy a file containing file and
directory patterns describing the file/directory paths that should be included
in the back-up.

The role implements the following:

* Installs a file with provided patterns in directory
  ``/etc/duply/main/patterns/``.
* Assembles/refresshes the main include pattern file at
  ``/etc/duply/main/include``.


Role dependencies
~~~~~~~~~~~~~~~~~

Depends on the following roles:

* **backup_client**


Parameters
~~~~~~~~~~

**backup_patterns_filename** (string, mandatory)
  Name of the backup patterns file. The file is stored in directory
  ``/etc/duply/main/patterns/``. This should be a unique filename amongst all
  roles. If role can be included multiple times, make sure the filename is
  always unique when depending on the backup role.

**backup_patterns** (list, optional, ``[]``)
  List of globbing patterns defining which files or directories should be
  backed-up.


Examples
~~~~~~~~

Here is an example configuration for setting-up the role:

.. code-block:: yaml

  - role: backup
    backup_patterns_filename: myapp
    backup_patters:
      - /var/www/myapp.example.com