summaryrefslogtreecommitdiffstats
path: root/roles/wiki
diff options
context:
space:
mode:
Diffstat (limited to 'roles/wiki')
-rw-r--r--roles/wiki/files/etc/nginx/sites-available/website47
-rw-r--r--roles/wiki/files/etc/nginx/sites-available/wiki49
-rw-r--r--roles/wiki/files/etc/systemd/system/ikiwiki.service23
-rw-r--r--roles/wiki/files/etc/systemd/system/ikiwiki.socket11
-rw-r--r--roles/wiki/files/var/lib/ikiwiki/IkiWiki/Plugin/pandoc.pm818
-rw-r--r--roles/wiki/files/var/lib/ikiwiki/fripost-wiki.setup18
-rw-r--r--roles/wiki/files/var/www/fripost.org/autoconfig/mail/config-v1.1.xml8
-rw-r--r--roles/wiki/handlers/main.yml11
-rw-r--r--roles/wiki/tasks/main.yml101
l---------roles/wiki/templates/etc/nginx/snippets/fripost.org.hpkp-hdr.j21
10 files changed, 1012 insertions, 75 deletions
diff --git a/roles/wiki/files/etc/nginx/sites-available/website b/roles/wiki/files/etc/nginx/sites-available/website
index 3513510..4aeb3db 100644
--- a/roles/wiki/files/etc/nginx/sites-available/website
+++ b/roles/wiki/files/etc/nginx/sites-available/website
@@ -1,52 +1,63 @@
server {
listen 80;
listen [::]:80;
server_name fripost.org;
server_name www.fripost.org;
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log info;
+ include /etc/lacme/nginx.conf;
- return 301 https://fripost.org$request_uri;
+ access_log /var/log/nginx/www.access.log;
+ error_log /var/log/nginx/www.error.log info;
+
+ location / {
+ return 301 https://$host$request_uri;
+ }
}
server {
- listen 443;
- listen [::]:443;
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
- server_name fripost.org;
+ server_name fripost.org;
+ server_name www.fripost.org;
- include ssl/config;
- # include the intermediate certificate, see
- # - https://www.ssllabs.com/ssltest/analyze.html?d=fripost.org
- # - http://nginx.org/en/docs/http/configuring_https_servers.html
- ssl_certificate /etc/nginx/ssl/fripost.org.chained.pem;
- ssl_certificate_key /etc/nginx/ssl/fripost.org.key;
+ access_log /var/log/nginx/www.access.log;
+ error_log /var/log/nginx/www.error.log info;
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log info;
+ include snippets/headers.conf;
+ add_header Content-Security-Policy
+ "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'none'; form-action https://www.paypal.com/; base-uri fripost.org www.fripost.org";
+
+ include snippets/ssl.conf;
+ ssl_certificate ssl/www.fripost.org.pem;
+ ssl_certificate_key ssl/www.fripost.org.key;
+ include snippets/fripost.org.hpkp-hdr;
+
+ gzip on;
+ gzip_vary on;
+ gzip_min_length 256;
+ gzip_types application/font-woff application/font-woff2 application/javascript application/json application/xml image/svg+xml image/x-icon text/css text/plain;
location / {
try_files $uri $uri/ =404;
index index.html;
root /var/lib/ikiwiki/public_html/fripost-wiki/website;
}
+ location = /ikiwiki.cgi { internal; }
location /static/ {
+ expires 30d;
+ try_files $uri =404;
alias /var/lib/ikiwiki/public_html/fripost-wiki/static/;
}
location /material/ {
alias /var/www/fripost.org/material/;
}
location /minutes/ {
alias /var/www/fripost.org/minutes/;
}
location /.well-known/autoconfig/ {
alias /var/www/fripost.org/autoconfig/;
}
-
- location = /ikiwiki.cgi {
- return 403;
- }
}
diff --git a/roles/wiki/files/etc/nginx/sites-available/wiki b/roles/wiki/files/etc/nginx/sites-available/wiki
index 304ea1a..b201ef5 100644
--- a/roles/wiki/files/etc/nginx/sites-available/wiki
+++ b/roles/wiki/files/etc/nginx/sites-available/wiki
@@ -1,54 +1,59 @@
server {
listen 80;
listen [::]:80;
server_name wiki.fripost.org;
+ include /etc/lacme/nginx.conf;
+
access_log /var/log/nginx/wiki.access.log;
error_log /var/log/nginx/wiki.error.log info;
location / {
location ~ ^/website(/.*)?$ { return 302 $scheme://fripost.org$1; }
- try_files $uri $uri/ =404;
- index index.html;
- root /var/lib/ikiwiki/public_html/fripost-wiki;
- }
-
- location = /ikiwiki.cgi {
- return 302 https://$host$request_uri;
+ return 301 https://$host$request_uri;
}
}
server {
- listen 443;
- listen [::]:443;
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
server_name wiki.fripost.org;
- include ssl/config;
- # include the intermediate certificate, see
- # - https://www.ssllabs.com/ssltest/analyze.html?d=wiki.fripost.org
- # - http://nginx.org/en/docs/http/configuring_https_servers.html
- ssl_certificate /etc/nginx/ssl/fripost.org.chained.pem;
- ssl_certificate_key /etc/nginx/ssl/fripost.org.key;
-
access_log /var/log/nginx/wiki.access.log;
error_log /var/log/nginx/wiki.error.log info;
+ include snippets/headers.conf;
+ add_header Content-Security-Policy
+ "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri wiki.fripost.org";
+
+ include snippets/ssl.conf;
+ ssl_certificate ssl/www.fripost.org.pem;
+ ssl_certificate_key ssl/www.fripost.org.key;
+ include snippets/fripost.org.hpkp-hdr;
+
+ gzip on;
+ gzip_vary on;
+ gzip_min_length 256;
+ gzip_types application/font-woff application/font-woff2 application/javascript application/json application/xml image/svg+xml image/x-icon text/css text/plain;
+
+ root /var/lib/ikiwiki/public_html/fripost-wiki;
+
+ location /static/ { expires 30d; try_files $uri =404; }
location / {
location ~ ^/website(/.*)?$ { return 302 $scheme://fripost.org$1; }
- try_files $uri $uri/ =404;
index index.html;
- root /var/lib/ikiwiki/public_html/fripost-wiki;
+ try_files $uri $uri/ =404;
}
location = /ikiwiki.cgi {
- fastcgi_param DOCUMENT_ROOT /var/lib/ikiwiki/public_html/fripost-wiki;
+ fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SCRIPT_FILENAME /var/lib/ikiwiki/public_html/ikiwiki.cgi;
fastcgi_index ikiwiki.cgi;
- include fastcgi/params;
- fastcgi_pass unix:/var/run/fcgiwrap.socket;
- gzip off;
+ include snippets/fastcgi.conf;
+ fastcgi_pass unix:/run/ikiwiki.socket;
+ gzip off; # protect against BREACH
}
}
diff --git a/roles/wiki/files/etc/systemd/system/ikiwiki.service b/roles/wiki/files/etc/systemd/system/ikiwiki.service
new file mode 100644
index 0000000..3ee7d66
--- /dev/null
+++ b/roles/wiki/files/etc/systemd/system/ikiwiki.service
@@ -0,0 +1,23 @@
+[Unit]
+Description=wiki compiler (CGI script)
+Documentation=https://ikiwiki.info/
+
+[Service]
+User=ikiwiki
+Group=ikiwiki
+ExecStart=/usr/sbin/fcgiwrap
+SyslogIdentifier=ikiwiki
+#
+# Hardening
+NoNewPrivileges=yes
+ReadWriteDirectories=/var/lib/ikiwiki/fripost-wiki
+ReadWriteDirectories=/var/lib/ikiwiki/public_html/fripost-wiki
+PrivateDevices=yes
+ProtectHome=yes
+ProtectSystem=strict
+ProtectControlGroups=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/wiki/files/etc/systemd/system/ikiwiki.socket b/roles/wiki/files/etc/systemd/system/ikiwiki.socket
new file mode 100644
index 0000000..8dc1a0e
--- /dev/null
+++ b/roles/wiki/files/etc/systemd/system/ikiwiki.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=wiki compiler (CGI script)
+Documentation=https://ikiwiki.info/
+
+[Socket]
+ListenStream=%t/ikiwiki.socket
+SocketUser=www-data
+SocketMode=0600
+
+[Install]
+WantedBy=sockets.target
diff --git a/roles/wiki/files/var/lib/ikiwiki/IkiWiki/Plugin/pandoc.pm b/roles/wiki/files/var/lib/ikiwiki/IkiWiki/Plugin/pandoc.pm
new file mode 100644
index 0000000..34bdd89
--- /dev/null
+++ b/roles/wiki/files/var/lib/ikiwiki/IkiWiki/Plugin/pandoc.pm
@@ -0,0 +1,818 @@
+#!/usr/bin/env perl
+
+package IkiWiki::Plugin::pandoc;
+
+use warnings;
+use strict;
+use IkiWiki;
+use FileHandle;
+use IPC::Open2;
+use File::Path qw/make_path/;
+use JSON;
+
+# activate with 'generate_$format' in meta; turn on all with 'generate_all_formats'.
+my %extra_formats = (
+ pdf => { ext=>'pdf', label=>'PDF', format=>'latex', extra=>[], order=>1 },
+ docx => { ext=>'docx', label=>'DOCX', format=>'docx', extra=>[], order=>2 },
+ odt => { ext=>'odt', label=>'ODT', format=>'odt', extra=>[], order=>3 },
+ beamer => { ext=>'beamer.pdf', label=>'Beamer', format=>'beamer', extra=>[], order=>4 },
+ revealjs => { ext=>'revealjs.html', label=>'RevealJS', format=>'revealjs', extra=>['--self-contained'], order=>5 },
+ epub => { ext=>'epub', label=>'EPUB', format=>'epub3', extra=>[], order=>6 },
+ latex => { ext=>'tex', label=>'LaTeX', format=>'latex', extra=>['--standalone'], order=>7 },
+);
+
+my @scalar_meta_keys = qw/
+ title date bibliography csl subtitle abstract summary description
+ version lang locale titlesort tag fripost_debug_inner
+ /;
+
+my @list_meta_keys = qw/
+ author
+ /;
+
+my @hash_meta_keys = qw/
+ experiment
+ /;
+
+my @list_hash_meta_keys = qw/
+ references
+ /;
+
+sub import {
+ my $markdown_ext = $config{pandoc_markdown_ext} || "mdwn";
+
+ # May be both a string with a single value, a string containing commas or an arrayref
+ if ($markdown_ext =~ /,/) {
+ $markdown_ext = [split /\s*,\s*/, $markdown_ext];
+ }
+
+ hook(type => "getsetup", id => "pandoc", call => \&getsetup);
+ hook(type => "pagetemplate", id => "pandoc", call => \&pagetemplate);
+ hook(type => "pageactions", id => "pandoc", call => \&pageactions);
+
+ if (ref $markdown_ext eq 'ARRAY') {
+ foreach my $mde (@$markdown_ext) {
+ hook(type => 'htmlize', id => $mde,
+ call => sub{ htmlize("markdown", @_) });
+ }
+ } else {
+ hook(type => "htmlize", id => $markdown_ext,
+ call => sub { htmlize("markdown", @_) });
+ }
+ if ($config{pandoc_latex}) {
+ hook(type => "htmlize", id => "tex",
+ call => sub { htmlize("latex", @_) });
+ }
+ if ($config{pandoc_rst}) {
+ hook(type => "htmlize", id => "rst",
+ call => sub { htmlize("rst", @_) });
+ }
+ if ($config{pandoc_textile}) {
+ hook(type => "htmlize", id => "textile",
+ call => sub { htmlize("textile", @_) });
+ }
+ if ($config{pandoc_mediawiki}) {
+ hook(type => "htmlize", id => "mediawiki",
+ call => sub { htmlize("mediawiki", @_) });
+ }
+ if ($config{pandoc_opml}) {
+ hook(type => "htmlize", id => "opml",
+ call => sub { htmlize("opml", @_) });
+ }
+ if ($config{pandoc_org}) {
+ hook(type => "htmlize", id => "org",
+ call => sub { htmlize("org", @_) });
+ }
+}
+
+
+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_command => {
+ type => "string",
+ example => "/usr/local/bin/pandoc",
+ description => "Path to pandoc executable",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_citeproc => {
+ type => "string",
+ example => "/usr/local/bin/pandoc-citeproc",
+ description => "Path to pandoc-citeproc executable",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_markdown_ext => {
+ type => "string",
+ example => "mdwn,md,markdown",
+ description => "File extension(s) for Markdown files handled by Pandoc",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_markdown_fmt => {
+ type => "string",
+ example => "markdown",
+ description => "Format string to use when processing files handled by Pandoc.",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_latex => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of LaTeX documents (extension=tex)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_rst => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of reStructuredText documents (extension=rst)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_textile => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of Textile documents (extension=textile)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_mediawiki => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of MediaWiki documents (extension=mediawiki)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_org => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of Emacs org-mode documents (extension=org)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_opml => {
+ type => "boolean",
+ example => 0,
+ description => "Enable Pandoc processing of OPML documents (extension=opml)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_smart => {
+ type => "boolean",
+ example => 1,
+ description => "Use smart quotes, dashes, and ellipses",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_obfuscate => {
+ type => "boolean",
+ example => 1,
+ description => "Obfuscate emails",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_html5 => {
+ type => "boolean",
+ example => 0,
+ description => "Generate HTML5",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_ascii => {
+ type => "boolean",
+ example => 0,
+ description => "Generate ASCII instead of UTF8",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_html_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for html",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_numsect => {
+ type => "boolean",
+ example => 0,
+ description => "Number sections",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_sectdiv => {
+ type => "boolean",
+ example => 0,
+ description => "Attach IDs to section DIVs instead of Headers",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_codeclasses => {
+ type => "string",
+ example => "",
+ description => "Classes to use for indented code blocks",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_math => {
+ type => "string",
+ example => "mathjax",
+ description => "How to process TeX math (mathjax, katex, mathml, mathjs, latexmathml, asciimathml, mimetex, webtex)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_math_custom_js => {
+ type => "string",
+ example => "",
+ description => "Link to local/custom javascript for math (or to server-side script for mimetex and webtex)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_math_custom_css => {
+ type => "string",
+ example => "",
+ description => "Link to local/custom CSS for math (requires appropriate pandoc_math setting)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_bibliography => {
+ type => "string",
+ example => "",
+ description => "Path to default bibliography file",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_csl => {
+ type => "string",
+ example => "",
+ description => "Path to CSL file (for references and bibliography)",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_csl_default_lang => {
+ type => "string",
+ example => "",
+ description => "Default language code (RFC 1766) for citations processing",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_filters => {
+ type => "string",
+ example => "",
+ description => "A comma-separated list of custom pandoc filters",
+ safe => 1,
+ rebuild => 1,
+ },
+ pandoc_latex_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for LaTeX and normal PDF output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_latex_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for LaTeX (and PDF) generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_beamer_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for Beamer PDF output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_beamer_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for Beamer PDF generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_pdf_export_cleanup => {
+ type => "boolean",
+ example => "0",
+ description => "Whether to clean up LaTeX auxiliary files after PDF generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_revealjs_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for Reveal.js slides output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_revealjs_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for Reveal.js slides generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_docx_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for MS Word (docx) output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_docx_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for DOCX generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_odt_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for OpenDocument (odt) output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_odt_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for ODT generation",
+ safe => 0,
+ rebuild => 0,
+ },
+ pandoc_epub_template => {
+ type => "string",
+ example => "",
+ description => "Path to pandoc template for EPUB3 output",
+ safe => 1,
+ rebuild => 0,
+ },
+ pandoc_epub_extra_options => {
+ type => "internal",
+ default => [],
+ description => "List of extra pandoc options for EPUB3 generation",
+ safe => 0,
+ rebuild => 0,
+ };
+}
+
+
+sub htmlize ($@) {
+ my $format = shift;
+ my %params = @_;
+ my $page = $params{page};
+ my $htmlformat = 'html';
+
+ local(*PANDOC_IN, *JSON_IN, *JSON_OUT, *PANDOC_OUT);
+ my @args = ();
+
+ # The default assumes pandoc is in PATH
+ my $command = $config{pandoc_command} || "pandoc";
+
+ if ($config{pandoc_smart}) {
+ push @args, '--smart';
+ }
+
+ if ($config{pandoc_obfuscate}) {
+ push @args, '--email-obfuscation=references';
+ } else {
+ push @args, '--email-obfuscation=none';
+ }
+
+ if ($config{pandoc_html5}) {
+ $htmlformat = 'html5';
+ }
+
+ if ($config{pandoc_ascii}) {
+ push @args, '--ascii';
+ }
+
+ if ($config{pandoc_numsect}) {
+ push @args, '--number-sections';
+ }
+
+ if ($config{pandoc_sectdiv}) {
+ push @args, '--section-divs';
+ }
+
+ if ($config{pandoc_codeclasses} && ($config{pandoc_codeclasses} ne "")) {
+ push @args, '--indented-code-classes=' . $config{pandoc_codeclasses};
+ }
+
+ # How to process math. Normally either mathjax or katex.
+ my %mathconf = map {($_=>"--$_")} qw(
+ jsmath mathjax latexmathml asciimathml mathml katex mimetex webtex
+ );
+ my %with_urls = qw/mimetex 1 webtex 1/;
+ my $mathopt = $1 if $config{pandoc_math} && $config{pandoc_math} =~ /(\w+)/;
+ my $custom_js = $config{pandoc_math_custom_js} || '';
+ # cleanup pandoc-prefixed keys from persistent meta
+ if (ref $pagestate{$page}{meta} eq 'HASH') {
+ my @delkeys = ();
+ foreach my $k (%{ $pagestate{$page}{meta} }) {
+ push @delkeys, $k if $k =~ /^pandoc_/;
+ }
+ delete $pagestate{$page}{meta}{$_} for @delkeys;
+ }
+ if ($mathopt && $mathconf{$mathopt}) {
+ if ($with_urls{$mathopt} && $custom_js) {
+ # In these cases, the 'custom js' is a misnomer: actually a server-side script
+ push @args, $mathconf{$mathopt} ."=". $custom_js;
+ } else {
+ push @args, $mathconf{$mathopt};
+ }
+ $pagestate{$page}{meta}{"pandoc_math"} = $mathopt;
+ $pagestate{$page}{meta}{"pandoc_math_$mathopt"} = 1;
+ $pagestate{$page}{meta}{"pandoc_math_custom_js"} = $custom_js if $custom_js;
+ }
+ # Convert to intermediate JSON format so that the title block
+ # can be parsed out
+ # We must omit the 'bibliography' parameter here, otherwise the list of
+ # references will be doubled.
+ my $markdown_fmt = $config{pandoc_markdown_fmt} || 'markdown';
+ my $to_json_pid = open2(*JSON_OUT, *PANDOC_OUT, $command,
+ '-f', $markdown_fmt,
+ '-t', 'json',
+ @args);
+ error("Unable to open $command") unless $to_json_pid;
+
+ # Workaround for perl bug (#376329)
+ require Encode;
+ my $content = Encode::encode_utf8($params{content});
+
+ # Protect inline plugin placeholders from being mangled by pandoc:
+ $content =~ s{<div class="inline" id="(\d+)"></div>}
+ {::INLINE::PLACEHOLDER::$1::}g;
+
+ print PANDOC_OUT $content;
+ close PANDOC_OUT;
+
+ my $json_content = <JSON_OUT>;
+ close JSON_OUT;
+
+ waitpid $to_json_pid, 0;
+
+ # Parse the title block out of the JSON and set the meta values
+ my $meta = undef;
+ my $decoded_json = decode_json($json_content);
+ # The representation of the meta block changed in pandoc version 1.18
+ if (ref $decoded_json eq 'HASH' && $decoded_json->{'meta'}) {
+ $meta = $decoded_json->{'meta'} || {}; # post-1.18 version
+ } elsif (ref $decoded_json eq 'ARRAY') {
+ $meta = $decoded_json->[0]->{'unMeta'} || {}; # pre-1.18 version
+ }
+ unless ($meta) {
+ warn "WARNING: Unexpected format for meta block. Incompatible version of Pandoc?\n";
+ }
+
+ # Get some selected meta attributes, more specifically:
+ # (title date bibliography csl subtitle abstract summary description
+ # version lang locale references author [+ num_authors primary_author]),
+ # as well as some configuration options (generate_*, *_extra_options, *_template).
+
+ my @format_keys = grep { $_ ne 'pdf' } keys %extra_formats;
+ my %scalar_meta = map { ($_=>undef) } @scalar_meta_keys;
+ $scalar_meta{$_.'_template'} = undef for @format_keys;
+ my %bool_meta = map { ("generate_$_"=>0) } keys %extra_formats;
+ my %list_meta = map { ($_=>[]) } (
+ @list_meta_keys, @list_hash_meta_keys, @hash_meta_keys);
+ $list_meta{$_.'_extra_options'} = [] for @format_keys;
+ my $have_bibl = 0;
+ foreach my $k (keys %scalar_meta) {
+ next unless $meta->{$k};
+ $scalar_meta{$k} = compile_string($meta->{$k}->{c});
+ # NB! Note that this is potentially risky, since pagestate is sticky, and
+ # we only cleanup the pandoc_* values in {meta}.
+ $pagestate{$page}{meta}{$k} = $scalar_meta{$k};
+ $pagestate{$page}{meta}{"pandoc_$k"} = $pagestate{$page}{meta}{$k};
+ }
+ foreach my $k (keys %bool_meta) {
+ my $gen_all = $meta->{generate_all_formats} || {};
+ next unless $meta->{$k} || $gen_all->{c};
+ my $val = $meta->{$k} ? $meta->{$k}->{c} : $gen_all->{c};
+ # simplifies matters with JSON::(PP::)Boolean objects
+ $val = 1 if $val == 1 || $val eq 'true';
+ if (ref $val || $val =~ /^\s*(?:off|no|false|0)\s*$/i) {
+ $bool_meta{$k} = 0;
+ } else {
+ $bool_meta{$k} = 1;
+ $pagestate{$page}{meta}{"pandoc_$k"} = 1;
+ }
+ }
+ foreach my $k (keys %list_meta) {
+ next unless $meta->{$k};
+ $list_meta{$k} = unwrap_c($meta->{$k});
+ $list_meta{$k} = [$list_meta{$k}] unless ref $list_meta{$k} eq 'ARRAY';
+ $have_bibl = 1 if $k eq 'references';
+ $pagestate{$page}{meta}{$k} = $list_meta{$k};
+ $pagestate{$page}{meta}{"pandoc_$k"} = $list_meta{$k};
+ }
+ # Try to add other keys as scalars, with pandoc_ prefix only.
+ foreach my $k (keys %$meta) {
+ next if exists $scalar_meta{$k} || exists $list_meta{$k};
+ eval {
+ $pagestate{$page}{meta}{"pandoc_$k"} = compile_string($meta->{$k}->{c});
+ };
+ }
+ my $num_authors = scalar @{ $list_meta{author} };
+ $scalar_meta{num_authors} = $num_authors;
+ $pagestate{$page}{meta}{num_authors} = $num_authors;
+ if ($num_authors) {
+ $scalar_meta{primary_author} = $list_meta{author}->[0];
+ $pagestate{$page}{meta}{author} = join(', ', @{$list_meta{author}});
+ $pagestate{$page}{meta}{pandoc_primary_author} = $scalar_meta{primary_author}
+ }
+
+ # The bibliography may be set in a Meta block in the page or in the .setup file.
+ # If both are present, the Meta block has precedence.
+ for my $bibl ($scalar_meta{bibliography}, $config{pandoc_bibliography}) {
+ if ($bibl) {
+ $have_bibl = 1;
+ $pagestate{$page}{meta}{pandoc_bibliography} = $bibl;
+ push @args, '--bibliography='.$bibl;
+ last;
+ }
+ }
+ # Similarly for the CSL file...
+ for my $cslfile ($scalar_meta{csl}, $config{pandoc_csl}) {
+ if ($cslfile) {
+ $pagestate{$page}{meta}{pandoc_csl} = $cslfile;
+ push @args, '--csl='.$cslfile;
+ last;
+ }
+ }
+ # If a default CSL language is specified, add that to args,
+ # (unless it is overridden by meta)
+ unless ($scalar_meta{lang} || $scalar_meta{locale}) {
+ if ($config{pandoc_csl_default_lang}) {
+ push @args, "--metadata=lang:".$config{pandoc_csl_default_lang};
+ }
+ }
+ # Turn on the pandoc-citeproc filter if either global bibliography,
+ # local bibliography or a 'references' key in Meta is present.
+ if ($have_bibl) {
+ my $citeproc = $config{pandoc_citeproc} || 'pandoc-citeproc';
+ push @args, "--filter=$citeproc";
+ }
+
+ # Other pandoc filters. Note that currently there is no way to
+ # configure a filter to run before pandoc-citeproc has done its work.
+ if ($config{pandoc_filters}) {
+ my @filters = split /\s*,\s*/, $config{pandoc_filters};
+ s/^["']//g for @filters; # get rid of enclosing quotes
+ foreach my $filter (@filters) {
+ push @args, "--filter=$filter";
+ }
+ }
+
+ # html_extra_options my be set in Meta block in the page or in the .setup
+ # file. If both are present, the Meta block has precedence, even if it is
+ # an empty list
+ my @html_args = @args;
+ if (ref $meta->{html_extra_options}{c} eq 'ARRAY') {
+ if (ref unwrap_c($meta->{html_extra_options}{c}) eq 'ARRAY') {
+ push @html_args, @{unwrap_c($meta->{html_extra_options}{c})};
+ } else {
+ push @html_args, unwrap_c($meta->{html_extra_options}{c});
+ }
+ } elsif (ref $config{'pandoc_html_extra_options'} eq 'ARRAY') {
+ push @html_args, @{$config{'pandoc_html_extra_options'}};
+ }
+
+ my $to_html_pid = open2(*PANDOC_IN, *JSON_IN, $command,
+ '-f', 'json',
+ '-t', $htmlformat,
+ @html_args);
+ error("Unable to open $command") unless $to_html_pid;
+
+ $pagestate{$page}{pandoc_extra_formats} = {};
+ foreach my $ext (keys %extra_formats) {
+ if ($bool_meta{"generate_$ext"}) {
+ export_file($page, $ext, $json_content, $command, @args);
+ } else {
+ remove_exported_file($page, $ext);
+ }
+ }
+
+ print JSON_IN $json_content;
+ close JSON_IN;
+
+ my @html = <PANDOC_IN>;
+ close PANDOC_IN;
+
+ waitpid $to_html_pid, 0;
+
+ $content = Encode::decode_utf8(join('', @html));
+
+ # Reinstate placeholders for inline plugin:
+ $content =~ s{::INLINE::PLACEHOLDER::(\d+)::}
+ {<div class="inline" id="$1"></div>}g;
+
+ return $content;
+}
+
+
+sub pagetemplate (@) {
+ my %params = @_;
+ my $page = $params{page};
+ my $template = $params{template};
+ foreach my $k (keys %{$pagestate{$page}{meta}}) {
+ next unless
+ (grep {/^$k$/} (
+ @scalar_meta_keys, @list_meta_keys,
+ @hash_meta_keys, @list_hash_meta_keys)) ||
+ ($k =~ /^(pandoc_)/);
+ $template->param($k => $pagestate{$page}{meta}{$k});
+ }
+ return $template;
+}
+
+sub pageactions {
+ my %args = @_;
+ my $page = $args{page};
+ my @links = ();
+ return unless $pagestate{$page}{pandoc_extra_formats};
+ my @exts = sort {
+ $extra_formats{$a}->{order} <=> $extra_formats{$b}->{order}
+ } keys %{ $pagestate{$page}{pandoc_extra_formats} };
+ foreach my $ext (@exts) {
+ my $url = $pagestate{$page}{pandoc_extra_formats}{$ext};
+ next unless $url;
+ my $label = $extra_formats{$ext}->{label} || $ext;
+ push @links, qq[
+ <a href="$url"
+ class="extra-format-link"
+ title="Download $label version of this page"
+ target="_blank">$label</a>
+ ];
+ }
+ return @links;
+}
+
+sub export_file {
+ my ($page, $ext, $json_content, $command, @args) = @_;
+ my ($export_path, $export_url) = _export_file_path_and_url($page, $ext);
+ my $subdir = $1 if $export_path =~ /(.*)\//;
+ my @extra_args = @{ $extra_formats{$ext}->{extra} };
+ my $eopt = $ext eq 'pdf' ? 'latex' : $ext;
+ # Note that template in meta OVERRIDES template in config,
+ # while extra_options in meta are ADDED to extra_options in config.
+ my $template = $pagestate{$page}{meta}{"pandoc_".$eopt."_template"}
+ || $config{"pandoc_".$eopt."_template"} || '';
+ if ($template) {
+ push @extra_args, ($ext =~ /^(docx|odt)$/
+ ? "--reference-$ext=$template"
+ : "--template=$template");
+ }
+ my $conf_extra = $config{"pandoc_".$eopt."_extra_options"};
+ my $conf_extra_custom = $pagestate{$page}{meta}{"pandoc_".$eopt."_extra_options"};
+ foreach my $cnf ($conf_extra, $conf_extra_custom) {
+ if (ref $cnf eq 'ARRAY' && @$cnf) {
+ push @extra_args, @$cnf;
+ }
+ }
+ my $pdf_cleanup = 0;
+ if (defined $pagestate{$page}{meta}{"pandoc_pdf_export_cleanup"}) {
+ $pdf_cleanup = $pagestate{$page}{meta}{"pandoc_pdf_export_cleanup"};
+ } elsif ($config{"pandoc_pdf_export_cleanup"}) {
+ $pdf_cleanup = 1;
+ }
+ # If the user has asked for native LaTeX bibliography handling in the
+ # extra_args for this export format (using --biblatex or --natbib),
+ # some extra care is needed. Among other things, we need an external
+ # tool for PDF generation. In this case, $indirect_pdf will be true.
+ my %maybe_non_citeproc = qw/latex 1 pdf 1 beamer 1/;
+ my $indirect_pdf = 0;
+ if ($maybe_non_citeproc{$ext} && grep { /^(?:--biblatex|--natbib)$/ } @extra_args) {
+ $indirect_pdf = 1 unless $ext eq 'latex'; # both for pdf and beamer
+ @args = grep { ! /--filter=.*pandoc-citeproc/ } @args;
+ }
+ eval {
+ if ($subdir && !-d $subdir) {
+ make_path($subdir) or die "Could not make_path $subdir: $!";
+ }
+ my $to_format = $extra_formats{$ext}->{format} || $ext;
+ my $tmp_export_path = $export_path;
+ $tmp_export_path =~ s/\.pdf$/.tex/ if $indirect_pdf;
+ open(EXPORT, "|-",
+ $command,
+ '-f' => 'json',
+ '-t' => $to_format,
+ '-o' => $tmp_export_path,
+ @args, @extra_args) or die "Could not open pipe for $ext: $!";
+ print EXPORT $json_content;
+ close EXPORT or die "Could not close pipe for $ext: $!";
+ if ($indirect_pdf && $tmp_export_path ne $export_path) {
+ my @latexmk_args = qw(-quiet -silent);
+ if (grep { /xelatex/ } @extra_args) {
+ push @latexmk_args, '-xelatex';
+ } elsif (grep { /lualatex/ } @extra_args) {
+ push @latexmk_args, '-lualatex';
+ } else {
+ push @latexmk_args, '-pdf';
+ }
+ chdir $subdir or die "Could not chdir to $subdir: $!";
+ my $plain_fn = $1 if $tmp_export_path =~ /([^\/]+)$/;
+ $plain_fn =~ s/\.tex//;
+ system('latexmk', @latexmk_args, $plain_fn) == 0
+ or die "Could not run latexmk for pdf generation ($export_path): $!";
+ if ($pdf_cleanup) {
+ system('latexmk', '-c', '-quiet', '-silent', $plain_fn) == 0
+ or die "Could not run latexmk for cleanup ($export_path): $!";
+ # These files are apparently not cleaned up by latexmk -c.
+ foreach ('run.xml', 'bbl') {
+ my $fn = "$subdir/$plain_fn.$_";
+ unlink($fn) if -f $fn;
+ }
+ }
+ }
+ $pagestate{$page}{pandoc_extra_formats}{$ext} = $export_url;
+ };
+ if ($@) {
+ warn "EXPORT ERROR FOR $page (format: $ext): $@\n";
+ }
+}
+
+sub remove_exported_file {
+ my ($page, $ext) = @_;
+ my ($export_path, $export_url) = _export_file_path_and_url($page, $ext);
+ if (-f $export_path) {
+ eval { unlink $export_path or die "Could not unlink $export_path: $!" };
+ if ($@) {
+ warn "WARNING: remove_exported_file; page=$page, ext=$ext: $@\n";
+ }
+ }
+}
+
+sub _export_file_path_and_url {
+ my ($page, $ext) = @_;
+ # the html file will end up in "$destdir/$page/index.html",
+ # while e.g. a pdf will be in "$destdir/$page/$page_minus_dirs.pdf".
+ my $extension = $extra_formats{$ext}->{ext} || $ext;
+ my $destdir = $config{destdir} || '.';
+ my $page_minus_dirs = $1 if $page =~ /([^\/]*)$/;
+ $page_minus_dirs ||= 'index';
+ my $export_path = "$destdir/$page/$page_minus_dirs.$extension";
+ my $export_url = $config{url};
+ $export_url .= "/" unless $export_url =~ /\/$/;
+ $export_url .= "$page/$page_minus_dirs.$extension";
+ return ($export_path, $export_url);
+}
+
+
+## compile_string and unwrap_c are used to make the meta data structures
+## easier to work with for perl.
+
+sub compile_string {
+ # Partially represents an item from the data structure in meta as a string.
+ my @uncompiled = @_;
+ return $uncompiled[0] if @uncompiled==1 && !ref($uncompiled[0]);
+ @uncompiled = @{$uncompiled[0]} if @uncompiled==1 && ref $uncompiled[0] eq 'ARRAY';
+ my $compiled_string = '';
+ foreach my $word_or_space (@uncompiled) {
+ next unless ref $word_or_space eq 'HASH';
+ my $type = $word_or_space->{'t'} || '';
+ $compiled_string .= compile_string(@{ $word_or_space->{c} }) if $type eq 'MetaInlines';
+ next unless $type eq 'Str' || $type eq 'Space' || $type eq 'MetaString';
+ $compiled_string .= $type eq 'Space' ? ' ' : $word_or_space->{c};
+ }
+ return $compiled_string;
+}
+sub unwrap_c {
+ # Unwrap pandoc's MetaLists, MetaInlines, etc.
+ # Finds the deepest-level scalar value for 'c' in the data structure.
+ # Lists with one element are replaced with the scalar, lists with more
+ # than one element are returned as an arrayref containing scalars.
+ #
+ # Elements containing hash as keys are unwrapped. That is to
+ # support *MetaList* containing *MetaMap* with keys pointing to
+ # *MetaInlines*. Reference are examples of that structure. (hash unwrap)
+ #
+ my $container = shift;
+ if (ref $container eq 'ARRAY' && @$container > 1) {
+ if (ref $container->[0] eq 'HASH' && $container->[0]->{t} =~ /^(?:Str|Space)$/) {
+ # handles scalar author fields
+ return join('', map { compile_string($_) } @$container);
+ } else {
+ return [map {unwrap_c($_)} @$container];
+ }
+ } elsif (ref $container eq 'ARRAY' && @$container) {
+ return unwrap_c($container->[0]);
+ } elsif (ref $container eq 'ARRAY') {
+ return;
+ } elsif (ref $container eq 'HASH' && $container->{c}) {
+ return unwrap_c($container->{c});
+ } elsif (ref $container eq 'HASH' && keys $container->%*) { # (hash unwrap)
+ return {map { $_ => unwrap_c($container->{$_}) } keys $container->%*};
+ } elsif (ref $container) {
+ return;
+ } else {
+ return $container;
+ }
+}
+
+1;
diff --git a/roles/wiki/files/var/lib/ikiwiki/fripost-wiki.setup b/roles/wiki/files/var/lib/ikiwiki/fripost-wiki.setup
index 6768629..4af3d59 100644
--- a/roles/wiki/files/var/lib/ikiwiki/fripost-wiki.setup
+++ b/roles/wiki/files/var/lib/ikiwiki/fripost-wiki.setup
@@ -6,70 +6,73 @@
# wrappers and build the wiki.
#
# Remember to re-run ikiwiki --setup any time you edit this file.
#
# name of the wiki
wikiname: Fripost wiki
# contact email for wiki
adminemail: admin@fripost.org
# users who are wiki admins
adminuser:
- gustaveek
- Grégoire
- moza
# users who are banned from the wiki
banned_users: []
# where the source of the wiki is located
srcdir: /var/lib/ikiwiki/fripost-wiki
# where to build the wiki
destdir: /var/lib/ikiwiki/public_html/fripost-wiki
# base url to the wiki
-url: http://wiki.fripost.org
+url: https://wiki.fripost.org
# url to the ikiwiki.cgi
-cgiurl: http://wiki.fripost.org/ikiwiki.cgi
+cgiurl: https://wiki.fripost.org/ikiwiki.cgi
# do not adjust cgiurl if CGI is accessed via different URL
reverse_proxy: 0
# filename of cgi wrapper to generate
cgi_wrapper: /var/lib/ikiwiki/public_html/ikiwiki.cgi
# mode for cgi_wrapper (can safely be made suid)
-cgi_wrappermode: 06755
+cgi_wrappermode: 0755
# number of seconds to delay CGI requests when overloaded
cgi_overload_delay: ''
# message to display when overloaded (may contain html)
cgi_overload_message: ''
# enable optimization of only refreshing committed changes?
only_committed_changes: 0
# rcs backend to use
rcs: git
# plugins to add to the default configuration
add_plugins:
- goodstuff
- websetup
- 404
- remove
- attachment
- highlight
- toc
- htmlbalance
- comments
+ - notifyemail
+ - getsource
###
- isWebsite
+ - pandoc
# plugins to disable
disable_plugins:
- smiley
# additional directory to search for template files
templatedir: /usr/share/ikiwiki/templates
# base wiki source location
underlaydir: /usr/share/ikiwiki/basewiki
# display verbose messages?
#verbose: 1
# log to syslog?
syslog: 1
# create output files named page/index.html?
usedirs: 1
# use '!'-prefixed preprocessor directives?
prefix_directives: 1
# use page/index.mdwn source files
indexpages: 0
# enable Discussion pages?
discussion: 1
# name of Discussion pages
@@ -118,43 +121,43 @@ cookiejar:
useragent: ikiwiki/3.20141016.2
######################################################################
# core plugins
# (editpage, git, htmlscrubber, inline, link, meta, parentlinks,
# templatebody)
######################################################################
# git plugin
# git hook to generate
git_wrapper: /var/lib/ikiwiki/wiki.fripost.org
# shell command for git_wrapper to run, in the background
#git_wrapper_background_command: git push github
# mode for git_wrapper (can safely be made suid)
#git_wrappermode: 06755
# git pre-receive hook to generate
#git_test_receive_wrapper: /git/wiki.git/hooks/pre-receive
# unix users whose commits should be checked by the pre-receive hook
#untrusted_committers: []
# gitweb url to show file history ([[file]] substituted)
-historyurl: http://git.fripost.org/fripost-wiki/tree/[[file]]
+historyurl: https://git.fripost.org/fripost-wiki/tree/[[file]]
# gitweb url to show a diff ([[file]], [[sha1_to]], [[sha1_from]], [[sha1_commit]], and [[sha1_parent]] substituted)
-diffurl: http://git.fripost.org/fripost-wiki/diff/[[file]]/?id=[[sha1_commit]]
+diffurl: https://git.fripost.org/fripost-wiki/diff/[[file]]/?id=[[sha1_commit]]
# where to pull and push changes (set to empty string to disable)
gitorigin_branch: origin
# branch that the wiki is stored in
gitmaster_branch: master
# htmlscrubber plugin
# PageSpec specifying pages not to scrub
#htmlscrubber_skip: '!*/Discussion'
# inline plugin
# enable rss feeds by default?
rss: 1
# enable atom feeds by default?
atom: 1
# allow rss feeds to be used?
#allowrss: 0
# allow atom feeds to be used?
#allowatom: 0
# urls to ping (using XML-RPC) on feed update
#pingurl: http://rpc.technorati.com/rpc/ping
@@ -266,41 +269,41 @@ allowed_attachments: virusfree() and (mimetype(application/mbox) or mimetype(tex
virus_checker: clamdscan -
# comments plugin
# PageSpec of pages where comments are allowed
comments_pagespec: tracker/*
# PageSpec of pages where posting new comments is not allowed
#comments_closed_pagespec: blog/controversial or blog/flamewar
# Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12"
#comments_pagename: ''
# Interpret directives in comments?
#comments_allowdirectives: 0
# Allow anonymous commenters to set an author name?
#comments_allowauthor: 0
# commit comments to the VCS
#comments_commit: 1
# Restrict formats for comments to (no restriction if empty)
#comments_allowformats: mdwn txt
# getsource plugin
# Mime type for returned source.
-#getsource_mimetype: text/plain; charset=utf-8
+getsource_mimetype: text/plain; charset=utf-8
# mirrorlist plugin
# list of mirrors
#mirrorlist: {}
# generate links that point to the mirrors' ikiwiki CGI
#mirrorlist_use_cgi: 1
# repolist plugin
# URIs of repositories containing the wiki's source
#repositories:
#- svn://svn.example.org/wiki/trunk
# search plugin
# path to the omega cgi program
#omega_cgi: /usr/lib/cgi-bin/omega/omega
# use google site search rather than internal xapian index?
#google_search: 1
# theme plugin
# name of theme to enable
@@ -394,20 +397,23 @@ comments_pagespec: tracker/*
# name of the recentchanges page
#recentchangespage: recentchanges
# number of changes to track
#recentchangesnum: 100
# rsync plugin
# command to run to sync updated pages
#rsync_command: rsync -qa --delete . user@host:/path/to/docroot/
# sidebar plugin
# show sidebar page on all pages?
#global_sidebars: 1
# tag plugin
# parent page tags are located under
#tagbase: tag
# autocreate new tag pages?
#tag_autocreate: 1
# commit autocreated tag pages
#tag_autocreate_commit: 1
+
+# pandoc plugin
+pandoc_html5: 1
diff --git a/roles/wiki/files/var/www/fripost.org/autoconfig/mail/config-v1.1.xml b/roles/wiki/files/var/www/fripost.org/autoconfig/mail/config-v1.1.xml
index e70b0be..00c2d0e 100644
--- a/roles/wiki/files/var/www/fripost.org/autoconfig/mail/config-v1.1.xml
+++ b/roles/wiki/files/var/www/fripost.org/autoconfig/mail/config-v1.1.xml
@@ -1,39 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="fripost.org">
<domain>fripost.org</domain>
- <displayName>Fripost &endash; demokratisk e-post</displayName>
+ <displayName>Fripost — demokratisk e-post</displayName>
<displayShortName>Fripost</displayShortName>
<incomingServer type="imap">
<hostname>imap.fripost.org</hostname>
<port>993</port>
<socketType>SSL</socketType>
<username>%EMAILADDRESS%</username>
<authentication>password-cleartext</authentication>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.fripost.org</hostname>
- <port>587</port>
- <socketType>STARTTLS</socketType>
+ <port>465</port>
+ <socketType>SSL</socketType>
<username>%EMAILADDRESS%</username>
<authentication>password-cleartext</authentication>
</outgoingServer>
- <documentation url="http://wiki.fripost.org/konfigurera/">
+ <documentation url="https://wiki.fripost.org/konfigurera/">
<descr lang="en">Configure your email client for Fripost</descr>
<descr lang="sv">Konfigurerar din e-postklient för Fripost</descr>
</documentation>
</emailProvider>
<webMail>
<loginPage url="https://mail.fripost.org/" />
<loginPageInfo url="https://mail.fripost.org/">
<username>%EMAILADDRESS%</username>
<usernameField id="rcmloginuser" name="_user" />
<passwordField id="rcmloginpwd" name="_pass" />
</loginPageInfo>
</webMail>
</clientConfig>
diff --git a/roles/wiki/handlers/main.yml b/roles/wiki/handlers/main.yml
index 42ae6ef..ac9ad2b 100644
--- a/roles/wiki/handlers/main.yml
+++ b/roles/wiki/handlers/main.yml
@@ -1,7 +1,16 @@
---
- name: Restart Nginx
service: name=nginx state=restarted
- name: Refresh ikiwiki
- sudo_user: ikiwiki
+ become_user: ikiwiki
command: ikiwiki --setup /var/lib/ikiwiki/fripost-wiki.setup --refresh --wrappers
+
+- name: systemctl daemon-reload
+ command: /bin/systemctl daemon-reload
+
+- name: Stop ikiwiki
+ service: name=ikiwiki.service state=stopped
+
+- name: Restart ikiwiki
+ service: name=ikiwiki.socket state=restarted
diff --git a/roles/wiki/tasks/main.yml b/roles/wiki/tasks/main.yml
index 7aa4d1d..74c11f8 100644
--- a/roles/wiki/tasks/main.yml
+++ b/roles/wiki/tasks/main.yml
@@ -1,113 +1,166 @@
- name: Install ikiwiki
- apt: pkg={{ item }}
- with_items:
+ apt: pkg={{ packages }}
+ vars:
+ packages:
- ikiwiki
+ - libauthen-passphrase-perl
- highlight-common
- libhighlight-perl
- libimage-magick-perl
+ - libmail-sendmail-perl
+ - libnet-dns-sec-perl
- fcgiwrap
+ - pandoc
+ ###
+ - fonts-font-awesome
+ - libjs-bootstrap4
+ - libjs-jquery
+
+- name: Stop and disable fcgiwrap socket
+ service: name=fcgiwrap.socket state=stopped enabled=false
+
+- name: Stop fcgiwrap service
+ service: name=fcgiwrap.service state=stopped
- name: Create a user 'ikiwiki'
user: name=ikiwiki system=yes
home=/var/lib/ikiwiki
shell=/usr/sbin/nologin
password=!
state=present
generate_ssh_key=yes
ssh_key_comment=ikiwiki@{{ ansible_fqdn }}
-- name: Add 'www-data' to the group 'ikiwiki'
- user: name=www-data groups=ikiwiki append=yes
-
- name: Create directory ~ikiwiki/IkiWiki/Plugin
file: path=/var/lib/ikiwiki/IkiWiki/Plugin
state=directory
owner=ikiwiki group=ikiwiki
mode=0755
-- name: Copy isWebsite plugin
- copy: src=var/lib/ikiwiki/IkiWiki/Plugin/isWebsite.pm
- dest=/var/lib/ikiwiki/IkiWiki/Plugin/isWebsite.pm
+- name: Copy ikiwiki plugins
+ copy: src=var/lib/ikiwiki/IkiWiki/Plugin/{{ item }}.pm
+ dest=/var/lib/ikiwiki/IkiWiki/Plugin/{{ item }}.pm
owner=root group=root
mode=0644
+ with_items:
+ - isWebsite
+ - pandoc
notify:
- Refresh ikiwiki
# Add the ikiwiki git wrapper as a post-update hook in the git repos in
# gitolite: "config hook.ikiwiki-wrapper = /var/lib/ikiwiki/wiki.fripost.org"
# where the 'git_wrapper' can be found in
# /var/lib/ikiwiki/fripost-wiki.setup
# To create a new wiki:
# $ /usr/bin/sudo -u ikiwiki git config --global user.name "Fripost Admins"
# $ /usr/bin/sudo -u ikiwiki git config --global user.email "admin@fripost.org"
# $ /usr/bin/sudo -u ikiwiki ikiwiki --setup /etc/ikiwiki/auto.setup
# ## Add ikiwiki's key to gitolite
-# sudo ln -s /var/lib/ikiwiki/wiki.fripost.org /var/lib/gitolite/repositories/fripost-wiki.git/hooks/post-update
+# ## Create post-update hook, cf. http://rtime.felk.cvut.cz/~sojka/blog/using-ikiwiki-with-gitolite/
# $ /usr/bin/sudo -u ikiwiki git clone ssh://gitolite@localhost/fripost-wiki.git
- name: Configure ikiwiki
copy: src=var/lib/ikiwiki/fripost-wiki.setup
dest=/var/lib/ikiwiki/fripost-wiki.setup
owner=root group=root
mode=0644
notify:
- Refresh ikiwiki
- name: Add fripost-wiki to /etc/ikiwiki/wikilist
lineinfile: dest=/etc/ikiwiki/wikilist
- "line=ikiwiki /var/lib/ikiwiki/fripost-wiki.setup"
+ line='ikiwiki /var/lib/ikiwiki/fripost-wiki.setup'
owner=root group=root
mode=0644
- meta: flush_handlers
-- name: Generate a private key and a X.509 certificate for Nginx
- command: genkeypair.sh x509
- --pubkey=/etc/nginx/ssl/fripost.org.pem
- --privkey=/etc/nginx/ssl/fripost.org.key
- --ou=WWW --cn=fripost.org --dns=fripost.org --dns=wiki.fripost.org
- -t rsa -b 4096 -h sha512
- register: r1
- changed_when: r1.rc == 0
- failed_when: r1.rc > 1
+- name: Copy ikiwiki service unit
+ copy: src=etc/systemd/system/ikiwiki.service
+ dest=/etc/systemd/system/ikiwiki.service
+ owner=root group=root
+ mode=0644
notify:
- - Restart Nginx
- tags:
- - genkey
+ - systemctl daemon-reload
+ - Stop ikiwiki
+
+- name: Copy ikiwiki socket unit
+ copy: src=etc/systemd/system/ikiwiki.socket
+ dest=/etc/systemd/system/ikiwiki.socket
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+ - Restart ikiwiki
+
+- name: Disable ikiwiki service
+ service: name=ikiwiki.service enabled=false
+
+- name: Start ikiwiki socket
+ service: name=ikiwiki.socket state=started enabled=true
+
+- meta: flush_handlers
- name: Copy /etc/nginx/sites-available/{wiki,website}
copy: src=etc/nginx/sites-available/{{ item }}
dest=/etc/nginx/sites-available/{{ item }}
owner=root group=root
mode=0644
- register: r2
+ register: r1
with_items:
- website
- wiki
notify:
- Restart Nginx
- name: Create /etc/nginx/sites-enabled/{wiki,website}
file: src=../sites-available/{{ item }}
dest=/etc/nginx/sites-enabled/{{ item }}
owner=root group=root
state=link force=yes
- register: r3
+ register: r2
with_items:
- website
- wiki
notify:
- Restart Nginx
+- name: Copy HPKP header snippet
+ # never modify the pined pubkeys as we don't want to lock out our users
+ template: src=etc/nginx/snippets/fripost.org.hpkp-hdr.j2
+ dest=/etc/nginx/snippets/fripost.org.hpkp-hdr
+ validate=/bin/false
+ owner=root group=root
+ mode=0644
+ register: r3
+ notify:
+ - Restart Nginx
+
+- name: Start Nginx
+ service: name=nginx state=started
+ when: not (r1.changed or r2.changed or r3.changed)
+
+- meta: flush_handlers
+
+- name: Fetch Nginx's X.509 certificate
+ # Ensure we don't fetch private data
+ become: False
+ fetch_cmd: cmd="openssl x509 -noout -pubkey"
+ stdin=/etc/nginx/ssl/www.fripost.org.pem
+ dest=certs/public/fripost.org.pub
+ tags:
+ - genkey
+
- name: Create directory /var/www/fripost.org/autoconfig/mail
file: path=/var/www/fripost.org/autoconfig/mail
state=directory
owner=root group=root
mode=0755
- name: Copy /var/www/fripost.org/autoconfig/mail/config-v1.1.xml
copy: src=var/www/fripost.org/autoconfig/mail/config-v1.1.xml
dest=/var/www/fripost.org/autoconfig/mail/config-v1.1.xml
owner=root group=root
mode=0644
diff --git a/roles/wiki/templates/etc/nginx/snippets/fripost.org.hpkp-hdr.j2 b/roles/wiki/templates/etc/nginx/snippets/fripost.org.hpkp-hdr.j2
new file mode 120000
index 0000000..a8ba598
--- /dev/null
+++ b/roles/wiki/templates/etc/nginx/snippets/fripost.org.hpkp-hdr.j2
@@ -0,0 +1 @@
+../../../../../../certs/hpkp-hdr.j2 \ No newline at end of file