Recent changes to this wiki:

Added a comment
diff --git a/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_2_f9eb3281ab2b9a4842a9292c0556bf0b._comment b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_2_f9eb3281ab2b9a4842a9292c0556bf0b._comment
new file mode 100644
index 0000000..a8d1e3c
--- /dev/null
+++ b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_2_f9eb3281ab2b9a4842a9292c0556bf0b._comment
@@ -0,0 +1,56 @@
+[[!comment format=mdwn
+ username="smcv"
+ avatar="http://cdn.libravatar.org/avatar/0ee943fe632ff995f6f0f25b7167d03b"
+ subject="comment 2"
+ date="2024-08-17T21:51:37Z"
+ content="""
+The patch above was based on the one from [[todo/use_a_native_systemd_unit_to_run_git-daemon]]. Updated patch with init script support:
+
+```
+From: Simon McVittie <smcv@debian.org>
+Date: Sat, 17 Aug 2024 21:36:12 +0100
+Subject: d/ikiwiki-hosting-web.{init,service}: Allow reading other
+ users' repositories
+
+Each website's git repository is owned by its own uid, and the
+git-daemon running as ikiwiki-anon needs to be able to read them all.
+
+Closes: #1076751
+---
+ debian/ikiwiki-hosting-web.init    | 4 ++++
+ debian/ikiwiki-hosting-web.service | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/debian/ikiwiki-hosting-web.init b/debian/ikiwiki-hosting-web.init
+index e92fb31..8065d2f 100755
+--- a/debian/ikiwiki-hosting-web.init
++++ b/debian/ikiwiki-hosting-web.init
+@@ -42,6 +42,10 @@ do_start()
+        #   2 if daemon could not be started
+        start-stop-daemon --start --chuid $gitdaemonuser:$gitdaemonuser --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+                || return 1
++
++       export GIT_CONFIG_COUNT=1
++       export GIT_CONFIG_KEY_0=safe.directory
++       export GIT_CONFIG_VALUE_0='*'
+        start-stop-daemon --start --chuid $gitdaemonuser:$gitdaemonuser --quiet --make-pidfile --pidfile $PIDFILE --background --exec $DAEMON -- \
+                $DAEMON_ARGS \
+                || return 2
+diff --git a/debian/ikiwiki-hosting-web.service b/debian/ikiwiki-hosting-web.service
+index a6c9a17..c9e0875 100644
+--- a/debian/ikiwiki-hosting-web.service
++++ b/debian/ikiwiki-hosting-web.service
+@@ -9,6 +9,11 @@ ExecStart=/usr/lib/git-core/git-daemon --reuseaddr --interpolated-path=/var/lib/
+ User=ikiwiki-anon
+ Group=ikiwiki-anon
+ Restart=on-failure
++# ikiwiki-anon needs to be willing to serve the git repositories of
++# websites owned by each site-specific uid
++Environment=GIT_CONFIG_COUNT=1
++Environment=GIT_CONFIG_KEY_0=safe.directory
++Environment=GIT_CONFIG_VALUE_0=*
+ 
+ [Install]
+ WantedBy=multi-user.target
+```
+"""]]

report regression with recent shadow/util-linux in Debian unstable
diff --git a/doc/bugs/assumes_that_useradd_creates_home_directories_a+rx.mdwn b/doc/bugs/assumes_that_useradd_creates_home_directories_a+rx.mdwn
new file mode 100644
index 0000000..145fa83
--- /dev/null
+++ b/doc/bugs/assumes_that_useradd_creates_home_directories_a+rx.mdwn
@@ -0,0 +1,34 @@
+ikiwiki-hosting assumes that the website uids' home directories will be created with at least a+x permissions. This was the default in Debian 12, but changes in shadow and/or util-linux in Debian unstable (I'm not sure which of these closely related packages is actually responsible) have resulted in the default becoming 0700, which doesn't allow `www-data` and `ikiwiki-anon` to read the web content and source git repo respectively.
+
+I think probably the way to solve this is to chmod the home directory to the permissions that ikiwiki-hosting expects; 0711 would probably be enough, but it doesn't seem like there's any real security benefit in denying the ability to list directory contents, because the contents of an ikiwiki-hosting website home directory are highly predictable anyway, and 0755 makes debugging easier. [[Patch]] below. --[[smcv]]
+
+---
+
+```
+From: Simon McVittie <smcv@debian.org>
+Date: Sat, 17 Aug 2024 21:19:09 +0100
+Subject: ikisite: Explicitly set 0755 permissions on website user's $HOME
+
+useradd in Debian 12 defaulted to this, but useradd in Debian 13
+will create home directories with more restricted permissions by
+default.
+
+Signed-off-by: Simon McVittie <smcv@debian.org>
+---
+ ikisite | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ikisite b/ikisite
+index 88a3def..a7276b5 100755
+--- a/ikisite
++++ b/ikisite
+@@ -1424,6 +1424,8 @@ sub usercreate {
+ 
+ 	# create skeleton
+ 	my $home=homedir($hostname);
++	# useradd in Debian 13 defaults to 0700 permissions on new $HOME
++	chmod(0755, $home);
+ 	mkdir("$home/.ssh") || error "mkdir $home/.ssh: $!";
+ 	mkdir("$home/tmp") || error "mkdir $home/tmp: $!";
+ 	foreach my $file (".ssh", "tmp") {
+```

Added a comment: proposed patch
diff --git a/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_1_4cc9c5b9d719091e45f6a8c9b68f918d._comment b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_1_4cc9c5b9d719091e45f6a8c9b68f918d._comment
new file mode 100644
index 0000000..51e4f7f
--- /dev/null
+++ b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45/comment_1_4cc9c5b9d719091e45f6a8c9b68f918d._comment
@@ -0,0 +1,40 @@
+[[!comment format=mdwn
+ username="smcv"
+ avatar="http://cdn.libravatar.org/avatar/0ee943fe632ff995f6f0f25b7167d03b"
+ subject="proposed patch"
+ date="2024-08-17T20:55:49Z"
+ content="""
+This is the least intrusive [[patch]] I've been able to come up with:
+
+```
+From: Simon McVittie <smcv@debian.org>
+Date: Sat, 17 Aug 2024 21:36:12 +0100
+Subject: d/ikiwiki-hosting-web.service: Allow reading other users'
+ repositories
+
+Each website's git repository is owned by its own uid, and the
+git-daemon running as ikiwiki-anon needs to be able to read them all.
+
+Closes: #1076751
+---
+ debian/ikiwiki-hosting-web.service | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/debian/ikiwiki-hosting-web.service b/debian/ikiwiki-hosting-web.service
+index a6c9a17..c9e0875 100644
+--- a/debian/ikiwiki-hosting-web.service
++++ b/debian/ikiwiki-hosting-web.service
+@@ -9,6 +9,11 @@ ExecStart=/usr/lib/git-core/git-daemon --reuseaddr --interpolated-path=/var/lib/
+ User=ikiwiki-anon
+ Group=ikiwiki-anon
+ Restart=on-failure
++# ikiwiki-anon needs to be willing to serve the git repositories of
++# websites owned by each site-specific uid
++Environment=GIT_CONFIG_COUNT=1
++Environment=GIT_CONFIG_KEY_0=safe.directory
++Environment=GIT_CONFIG_VALUE_0=*
+ 
+ [Install]
+ WantedBy=multi-user.target
+```
+"""]]

correct link syntax
diff --git a/doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn b/doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn
index 4973dc2..dfee49e 100644
--- a/doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn
+++ b/doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn
@@ -1,3 +1,3 @@
-Philip Hands [reported](https://salsa.debian.org/debian/ikiwiki-hosting/-/merge_requests/2) that Certbot 2.x (Debian 12) generates ECDSA keys by default, not RSA keys like older versions. ikiwiki-hosting only checks for valid RSA keys, causing SSL to be disabled for newly-reconfigured sites. He attached a [[patch]] in the merge request: https://salsa.debian.org/debian/ikiwiki-hosting/-/blob/790b509a075b3f661b8feb77fcb12fe3d0118dd9/debian/patches/accept-ec-keys-as-valid-in-addition-to-r.patch
+Philip Hands [reported](https://salsa.debian.org/debian/ikiwiki-hosting/-/merge_requests/2) that Certbot 2.x (Debian 12) generates ECDSA keys by default, not RSA keys like older versions. ikiwiki-hosting only checks for valid RSA keys, causing SSL to be disabled for newly-reconfigured sites. He attached a [[patch]] in the merge request: <https://salsa.debian.org/debian/ikiwiki-hosting/-/blob/790b509a075b3f661b8feb77fcb12fe3d0118dd9/debian/patches/accept-ec-keys-as-valid-in-addition-to-r.patch>
 
 --[[smcv]]

rename bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn to bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn
diff --git a/doc/bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn b/doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn
similarity index 100%
rename from doc/bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn
rename to doc/bugs/treats_EC_keys_issued_by_Certbot_2.x_as_invalid.mdwn

report incompatibility with Certbot 2.x
diff --git a/doc/bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn b/doc/bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn
new file mode 100644
index 0000000..4973dc2
--- /dev/null
+++ b/doc/bugs/treats_EC_keys_issued_by_letsencrypt_as_invalid.mdwn
@@ -0,0 +1,3 @@
+Philip Hands [reported](https://salsa.debian.org/debian/ikiwiki-hosting/-/merge_requests/2) that Certbot 2.x (Debian 12) generates ECDSA keys by default, not RSA keys like older versions. ikiwiki-hosting only checks for valid RSA keys, causing SSL to be disabled for newly-reconfigured sites. He attached a [[patch]] in the merge request: https://salsa.debian.org/debian/ikiwiki-hosting/-/blob/790b509a075b3f661b8feb77fcb12fe3d0118dd9/debian/patches/accept-ec-keys-as-valid-in-addition-to-r.patch
+
+--[[smcv]]

forward Debian bug 1076751
diff --git a/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45.mdwn b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45.mdwn
new file mode 100644
index 0000000..ed64c94
--- /dev/null
+++ b/doc/bugs/git-daemon_will_not_export_source.git_with_git_2.45.mdwn
@@ -0,0 +1,14 @@
+There is a [behaviour change in git 2.45.x](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1076750) in which git-daemon(1) no longer allows exporting a git repo owned by a different uid unless the repository has been explicitly marked as safe.
+
+This resulted in [an automated test regression for ikiwiki-hosting](https://bugs.debian.org/1076751): the test asserts that we can `git clone` a newly created site's `source.git`, but the git-daemon(1) is running as `ikiwiki-anon` and the `source.git` is owned by `w-example`, so git-daemon(1) refuses to serve it.
+
+I've asked the git maintainers whether this particular behaviour change was intentional, and if yes, what the recommended way is to reassure git-daemon(1) that it can, in fact, serve another user's git repo. If the behaviour change was intentional, it might be necessary for `ikiwiki-hosting-web` to write out configuration to achieve that.
+
+A crude version is to write
+
+    [safe]
+    directory=*
+
+into `/var/lib/ikiwiki-hosting-web/git/.gitconfig`, but I'm hoping that the git maintainers can suggest something a little more targeted.
+
+--[[smcv]]

add news item for ikiwiki-hosting 0.20220717
diff --git a/doc/news/version_0.20170622.mdwn b/doc/news/version_0.20170622.mdwn
deleted file mode 100644
index 42aa5bd..0000000
--- a/doc/news/version_0.20170622.mdwn
+++ /dev/null
@@ -1,20 +0,0 @@
-ikiwiki-hosting 0.20170622 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * [ [[Joey Hess|joey]] ]
-   * remove, letsnotencrypt: Remove Lets Encrypt renewal file, to avoid
-     the cron job trying to renew deleted sites.
-   * Fix deletion of sites that use https over the web interface.
-   * HTTP Strict Transport Security (HSTS) is enabled for all
-     sites that have `redirect_to_https` set in their configuration.
-     Thanks, Antoine Beaupré.
-   * Improve `ikisite backup` to lock the wiki for a much shorter period of time.
-   * Remove `.ikiwiki/sessions.db` from the ikisite backup, as the file can be
-     rather large, and losing it only means users have to log back in sooner
-     than would otherwise be the case.
-   * ikisite-wrapper: Allow `ikisite enable` to be run via the wrapper.
-     The CGI uses this to update the site config of an already enabled site
-     when enabling eg `redirect_to_https` or adding a DNS alias.
- * [ [[Simon McVittie|smcv]] ]
-   * debian/copyright: Use preferred https URL for Format
-   * debian/control: Declare compliance with Debian Policy 4.0.0
-   * debian: Update to debhelper compat level 10"""]]
diff --git a/doc/news/version_0.20220717.mdwn b/doc/news/version_0.20220717.mdwn
new file mode 100644
index 0000000..ddc7406
--- /dev/null
+++ b/doc/news/version_0.20220717.mdwn
@@ -0,0 +1,8 @@
+ikiwiki-hosting 0.20220717 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  [ Simon McVittie ]
+  * ikisite backup: Create the bundle as the site's user, so the backup
+    works when git run as root would consider the repository untrusted.
+  * debian: Depend on python3-docutils instead of python-docutils
+    Closes: #[945656](http://bugs.debian.org/945656)
+  * debian: smoke-files: The makesite test needs an extra file copied
+  * debian: Use Testsuite: autopkgtest-pkg-perl"""]]
\ No newline at end of file

merged remotes/smcv/deb-packaging
diff --git a/CHANGELOG b/CHANGELOG
index c1a07de..a09849e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,10 @@ ikiwiki-hosting (0.20220717) UNRELEASED; urgency=medium
   [ Simon McVittie ]
   * ikisite backup: Create the bundle as the site's user, so the backup
     works when git run as root would consider the repository untrusted.
+  * debian: Depend on python3-docutils instead of python-docutils
+    Closes: #945656
+  * debian: smoke-files: The makesite test needs an extra file copied
+  * debian: Use Testsuite: autopkgtest-pkg-perl
 
  -- Joey Hess <id@joeyh.name>  Mon, 03 Apr 2023 15:34:05 -0400
 
diff --git a/doc/todo/various_small_changes_from_Debian_packaging.mdwn b/doc/todo/various_small_changes_from_Debian_packaging.mdwn
index 6988425..98761fc 100644
--- a/doc/todo/various_small_changes_from_Debian_packaging.mdwn
+++ b/doc/todo/various_small_changes_from_Debian_packaging.mdwn
@@ -21,3 +21,5 @@
 <https://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/shortlog/refs/heads/deb-packaging>
 
 --[[smcv]]
+
+> [[merged|done]] --[[Joey]]

comment
diff --git a/doc/todo/use_a_native_systemd_unit_to_run_git-daemon/comment_1_9405858f81b6346937b416843fe0de87._comment b/doc/todo/use_a_native_systemd_unit_to_run_git-daemon/comment_1_9405858f81b6346937b416843fe0de87._comment
new file mode 100644
index 0000000..9a2e54f
--- /dev/null
+++ b/doc/todo/use_a_native_systemd_unit_to_run_git-daemon/comment_1_9405858f81b6346937b416843fe0de87._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2023-04-03T19:37:45Z"
+ content="""
+The service file looks ok.
+
+I'm a bit unsure about the two ikiwiki-hosting.conf that don't get moved to
+the service file. If a user has changed those, they will have to notice the
+conffile change and follow through to edit the service file based on
+comments in the conffile.
+
+Also, ikisite uses those configs, so we lose DRY and the user has to
+remember to change a config in two places if they change it later. (To be
+fair, the postinst also creates a user based on those configs so changing
+them is already involved and probably noone actually does.)
+"""]]

changelog and close
diff --git a/CHANGELOG b/CHANGELOG
index 5c83fd3..c1a07de 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,11 @@
+ikiwiki-hosting (0.20220717) UNRELEASED; urgency=medium
+
+  [ Simon McVittie ]
+  * ikisite backup: Create the bundle as the site's user, so the backup
+    works when git run as root would consider the repository untrusted.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 03 Apr 2023 15:34:05 -0400
+
 ikiwiki-hosting (0.20220716) upstream; urgency=medium
 
   * Fix the test suite to work when ikiwiki-hosting is not installed.
diff --git a/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
index cba0bce..672d370 100644
--- a/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
+++ b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
@@ -12,3 +12,6 @@ Fixed in my `backup-with-newer-git` [[branch|patch]]:
 <http://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/shortlog/refs/heads/backup-with-newer-git>
 
 --[[smcv]]
+
+> [[merged|done]], thanks. I will make a release with this today.
+> --[[Joey]]

forward a change from Debian
diff --git a/doc/todo/use_a_native_systemd_unit_to_run_git-daemon.mdwn b/doc/todo/use_a_native_systemd_unit_to_run_git-daemon.mdwn
new file mode 100644
index 0000000..e8e4a3a
--- /dev/null
+++ b/doc/todo/use_a_native_systemd_unit_to_run_git-daemon.mdwn
@@ -0,0 +1,10 @@
+Wrapping an LSB init script with systemd-sysv-generator(8) is not an ideal way to run a system service. In particular, systemd-sysv-generator can't tell whether an init script is meant to be the equivalent of systemd Type=forking (like /etc/init.d/dbus) or the equivalent of systemd Type=oneshot (like /etc/init.d/sudo), so it has no choice but to create a weird mixture of the two which doesn't reliably detect errors.
+
+I suspect that a future version of systemd will deprecate systemd-sysv-generator and stop installing it by default, although I don't think any such plans have been announced yet.
+
+Here's a native systemd unit equivalent of the LSB init script, which is much shorter and simpler than the init script itself:
+<https://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/shortlog/refs/heads/native-systemd-unit>
+
+I haven't removed the LSB init script, so users of non-systemd init can continue to use it as-is.
+
+--[[smcv]]

propose various small packaging changes
diff --git a/doc/todo/various_small_changes_from_Debian_packaging.mdwn b/doc/todo/various_small_changes_from_Debian_packaging.mdwn
new file mode 100644
index 0000000..6988425
--- /dev/null
+++ b/doc/todo/various_small_changes_from_Debian_packaging.mdwn
@@ -0,0 +1,23 @@
+* Use Testsuite: autopkgtest-pkg-perl
+    
+    Recent versions of autodep8 will append our debian/tests/control to the
+    one they generate, so we no longer need to replicate what autodep8 would
+    have produced.
+
+* d/tests/pkg-perl/smoke-files: The makesite test needs an extra file copied
+    
+    Fixes: 278d8ae4 "Fix the test suite to work when ikiwiki-hosting is not installed"
+
+* d/control: Depend on python3-docutils instead of python-docutils
+    
+    This catches up with the corresponding change to ikiwiki's Suggests in
+    version 3.20180105-1.
+    
+    Also explicitly depend on python3, again matching ikiwiki's Suggests.
+    
+    Closes: [#945656](https://bugs.debian.org/945656)
+
+[[Branch|patch]]:
+<https://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/shortlog/refs/heads/deb-packaging>
+
+--[[smcv]]

propose fix
diff --git a/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
index ac541e0..cba0bce 100644
--- a/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
+++ b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
@@ -7,3 +7,8 @@ error: git failed
 ```
 
 I think this is because git now distrusts directories not owned by the current user. The solution seems to be to sudo to the site's owning user before taking the backup.
+
+Fixed in my `backup-with-newer-git` [[branch|patch]]:
+<http://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/shortlog/refs/heads/backup-with-newer-git>
+
+--[[smcv]]

new bug report
diff --git a/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
new file mode 100644
index 0000000..ac541e0
--- /dev/null
+++ b/doc/bugs/ikisite_backup_fails_on_Debian_12___40__git_2.39.2__41__.mdwn
@@ -0,0 +1,9 @@
+After upgrading to Debian 12:
+
+```
+# ikisite backup REDACTED --filename=/dev/null
+fatal: Need a repository to create a bundle.
+error: git failed
+```
+
+I think this is because git now distrusts directories not owned by the current user. The solution seems to be to sudo to the site's owning user before taking the backup.

add news item for ikiwiki-hosting 0.20220716
diff --git a/doc/news/version_0.20161219.mdwn b/doc/news/version_0.20161219.mdwn
deleted file mode 100644
index d0b0de0..0000000
--- a/doc/news/version_0.20161219.mdwn
+++ /dev/null
@@ -1,16 +0,0 @@
-ikiwiki-hosting 0.20161219 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * [ Joey Hess ]
-   * Initial support for Lets Encrypt.
-   * The use\_letsencrypt setting can be set for a site by running
-     ikisite letsencrypt domain, and it will attempt to get the certificate
-     for it using certbot.
-   * ikisite domains: Update certificate using certbot when set of domains
-     changes.
-   * Added ikisite maintaincerts to request/renew Lets Encrypt certs as needed,
-     and added it to the daily cron job.
-   * The files /etc/ikiwiki-hosting/config/$username/domain.{crt,key,chain}
-     are used, when they exist, in preference to the files
-     /etc/ikiwiki-hosting/config/$username/ssl.{key,crt}. This allows
-     a site with multiple domains to have different certificates
-     for them. The Lets Encrypt support uses this."""]]
\ No newline at end of file
diff --git a/doc/news/version_0.20220716.mdwn b/doc/news/version_0.20220716.mdwn
new file mode 100644
index 0000000..e35fbf8
--- /dev/null
+++ b/doc/news/version_0.20220716.mdwn
@@ -0,0 +1,2 @@
+ikiwiki-hosting 0.20220716 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * Fix the test suite to work when ikiwiki-hosting is not installed."""]]
\ No newline at end of file

Fix the test suite to work when ikiwiki-hosting is not installed
Based on a patch by Simon McVittie.
diff --git a/CHANGELOG b/CHANGELOG
index de87f40..85cba9d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ikiwiki-hosting (0.20220716) UNRELEASED; urgency=medium
+
+  * Fix the test suite to work when ikiwiki-hosting is not installed.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 01 Aug 2022 11:35:23 -0400
+
 ikiwiki-hosting (0.20220715) upstream; urgency=medium
 
   * Avoid directly running init scripts, instead use the service command.
diff --git a/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn
index ef388be..00f1564 100644
--- a/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn
+++ b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn
@@ -6,3 +6,5 @@ This seems to have been triggered by adding a call to `IkiWiki::Hosting::readcon
 (`git fetch https://git.pseudorandom.co.uk/git/smcv/ikiwiki-hosting.git build-time-makesite-test`)
 
 --smcv
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed/comment_1_bf9e6192ca9cd1b1850577e8981c6cda._comment b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed/comment_1_bf9e6192ca9cd1b1850577e8981c6cda._comment
new file mode 100644
index 0000000..c1ee6f9
--- /dev/null
+++ b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed/comment_1_bf9e6192ca9cd1b1850577e8981c6cda._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-01T15:31:40Z"
+ content="""
+This fix is ok, but I don't see any reason to check `INSTALLED_TESTS`,
+that is not a concept that this test suite knows about,
+and AFAICS the source tree will always be present when running tests.
+
+I've applied a version of the fix without that check. Am making a release
+to fix this since I suppose you hit it while updating to the previous
+release.
+"""]]
diff --git a/t/makesite.t b/t/makesite.t
index 0a83a3e..84f5ea3 100755
--- a/t/makesite.t
+++ b/t/makesite.t
@@ -2,9 +2,13 @@
 use strict;
 use warnings;
 no warnings 'redefine';
+use IkiWiki;
 use IkiWiki::Plugin::makesite;
+use Cwd qw(getcwd);
 use Test::More 'no_plan';
 
+$config{ikisite_conffile} = getcwd.'/ikiwiki-hosting.conf';
+
 # Synthetic test functions.
 sub IkiWiki::Hosting::site_addresses {
 	return "2.2.2.2", "fe80::4878:f:21a:2";

open bug with patch
diff --git a/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn
new file mode 100644
index 0000000..ef388be
--- /dev/null
+++ b/doc/bugs/makesite_test_fails_if_ikiwiki-hosting_is_not_installed.mdwn
@@ -0,0 +1,8 @@
+When building ikiwiki-hosting in a container/autobuilder environment where it is not already installed, the `makesite.t` test fails because `/etc/ikiwiki-hosting/ikiwiki-hosting.conf` doesn't exist yet.
+
+This seems to have been triggered by adding a call to `IkiWiki::Hosting::readconfig` in the `makesite` plugin.
+
+[Proposed fix](https://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git/commitdiff/refs/heads/build-time-makesite-test)
+(`git fetch https://git.pseudorandom.co.uk/git/smcv/ikiwiki-hosting.git build-time-makesite-test`)
+
+--smcv

add news item for ikiwiki-hosting 0.20220715
diff --git a/doc/news/version_0.20160811.mdwn b/doc/news/version_0.20160811.mdwn
deleted file mode 100644
index 4614d05..0000000
--- a/doc/news/version_0.20160811.mdwn
+++ /dev/null
@@ -1,8 +0,0 @@
-ikiwiki-hosting 0.20160811 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Explicitly remove current working directory from Perl's library
-     search path, mitigating CVE-2016-1238 (see [[!debbug 588017]])
-   * Debian packaging:
-     - Add a simple autopkgtest for creating and deleting a site
-     - Standards-Version: 3.9.8 (no changes required)
-     - debian/rules: enable compiler hardening"""]]
diff --git a/doc/news/version_0.20220715.mdwn b/doc/news/version_0.20220715.mdwn
new file mode 100644
index 0000000..5fa6235
--- /dev/null
+++ b/doc/news/version_0.20220715.mdwn
@@ -0,0 +1,21 @@
+ikiwiki-hosting 0.20220715 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * Avoid directly running init scripts, instead use the service command.
+  * Avoid running apache2ctl graceful which may start an apache process
+    outside of systemd control (see bug #927302).
+    (But note that certbot still uses apache2ctl graceful.)
+  * As ssh RSA keys are being deprecated in an upcoming ssh release,
+    the gitpush plugin will generate a Ed25519 key for the site if one does
+    not yet exist.
+  * The gitpush plugin, when listing the site's ssh keys, will list all
+    available public keys, rather than just one.
+  * Fix anonymous git push to branchable sites, which has been broken
+    since 2018 by a git behavior change.
+  * Fix ACL setting in ikisite enable to come after chmod, which otherwise
+    would mess up the ACLs and break anonymous git push.
+  * Added hostname\_stopwords config that can be used to prevent use of
+    particular words in names of sites.
+  * ikisite enable, ikisite letsencrypt: When a fullchain file is available,
+    use it for apache's SSLCertificateFile, and do not use the chain file.
+    This avoids a problem with leteencrypt and apache where apache serves
+    up 2 copies of the certificate, one from the cert file, and one from
+    the fullchain file, which confuses some SSL clients."""]]
\ No newline at end of file

add
diff --git a/doc/todo/avoid_third_checkout_of_source_for_setup_branch.mdwn b/doc/todo/avoid_third_checkout_of_source_for_setup_branch.mdwn
new file mode 100644
index 0000000..145e921
--- /dev/null
+++ b/doc/todo/avoid_third_checkout_of_source_for_setup_branch.mdwn
@@ -0,0 +1,6 @@
+The setup branch is checked out into a site user's home directory, and this
+means that ~/.git is another copy of the source, on top of the two in
+source/.git and source.git. This can use a lot of space, although often
+nothing pulls updates to mater into that repo if lucky.
+
+git has ways now to avoid this problem, eg multiple worktrees. --[[Joey]]

comment
diff --git a/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails/comment_1_b84b1d68127a81e9fb1837b2bd9aea03._comment b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails/comment_1_b84b1d68127a81e9fb1837b2bd9aea03._comment
new file mode 100644
index 0000000..f275ae8
--- /dev/null
+++ b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails/comment_1_b84b1d68127a81e9fb1837b2bd9aea03._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-10-02T15:50:38Z"
+ content="""
+The patch seems to not detect the undefined value, so it will still crash.
+
+Compare:
+
+	perl -e 'use warnings; use strict; foreach my $foo (@{ undef() }) { print $foo }'
+	Can't use an undefined value as an ARRAY reference at -e line 1.
+
+	perl -e 'use warnings; use strict; my $l=@{ undef() } ; foreach my $foo (@{$l}) { print $foo }'
+	Can't use an undefined value as an ARRAY reference at -e line 1.
+
+"""]]

ping
diff --git a/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn
index fafbe7e..36a2a81 100644
--- a/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn
+++ b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn
@@ -39,3 +39,5 @@ index c55a97d..37981f1 100644
 
 
 ... no? --[[anarcat]]
+
+> ping! there's a [[!taglink patch]] here. :) -- [[anarcat]]

add news item for ikiwiki-hosting 0.20180719
diff --git a/doc/news/version_0.20160123.mdwn b/doc/news/version_0.20160123.mdwn
deleted file mode 100644
index 755642f..0000000
--- a/doc/news/version_0.20160123.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-ikiwiki-hosting 0.20160123 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Fix the escaping of `{` in HostingAutomator by also escaping the `}`,
-     fixing a regression that broke `ikisite create`"""]]
diff --git a/doc/news/version_0.20180719.mdwn b/doc/news/version_0.20180719.mdwn
new file mode 100644
index 0000000..b11b1e9
--- /dev/null
+++ b/doc/news/version_0.20180719.mdwn
@@ -0,0 +1,14 @@
+ikiwiki-hosting 0.20180719 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Joey Hess ]
+   * ikisite: Deleting per-domain letsencrypt cert when a wildcard cert
+     exists was too dangerous and buggy, including sometimes deleting the
+     letsencrypt wildcard cert. Removed that behavior; any per-domain cert
+     will be used in preference to the wildcard cert.
+   * Further fix to IkiWiki::Hosting for syslog name change.
+     (Fixes ikidns)
+   * ikidns: Fix typo in letsencrypt command.
+ * [ Simon McVittie ]
+   * debian: Pass dpkg-buildflags CFLAGS to make
+   * debian: Override dh\_missing to detect any files that are installed by
+     dh\_auto\_install but not packaged"""]]
\ No newline at end of file

Announce 0.20180610
diff --git a/doc/news/version_0.20160121.mdwn b/doc/news/version_0.20160121.mdwn
deleted file mode 100644
index cb872eb..0000000
--- a/doc/news/version_0.20160121.mdwn
+++ /dev/null
@@ -1,15 +0,0 @@
-ikiwiki-hosting 0.20160121 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * [ [[Joey Hess|joey]] ]
-   * Fix looping redirection when `redirect_to_https` is set.
-     Thanks, [[Antoine Beaupré|anarcat]].
-   * controlpanel: Display unfocused site buttons with low opacity, but still
-     display them. This is an accessability fix; the old hiding method broken
-     caret browsing and screenreaders.
- * [ [[Simon McVittie|smcv]] ]
-   * d/control: use https for Homepage
-   * d/control: use pkg-perl autopkgtest setup
-   * Fix "unescaped left brace in regex is deprecated" with Perl 5.22
-   * Normalize packaging through `wrap-and-sort -abst`
-   * Depend on libimage-magick-perl in preference to transitional
-     perlmagick package, similar to [#789221](https://bugs.debian.org/789221) in ikiwiki"""]]
diff --git a/doc/news/version_0.20180610.mdwn b/doc/news/version_0.20180610.mdwn
new file mode 100644
index 0000000..4cb647c
--- /dev/null
+++ b/doc/news/version_0.20180610.mdwn
@@ -0,0 +1,31 @@
+ikiwiki-hosting 0.20180610 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Joey Hess ]
+   * Renamed IkiWiki::Hosting::syslog to IkiWiki::Hosting::logger to avoid
+     conflict with Sys::Syslog::syslog.
+   * Prevent ikisite letsencrypt from unncessarily reloading apache when
+     there is no configuration change. ikisite maintaincerts runs it once
+     per site, and the resulting many reloads of apache close together
+     tended to cause apache to fall over, due to bug #873115.
+   * ikiwiki-hosting.conf: Removed wildcard\_ssl\_cert, wildcard\_ssl\_key,
+     wildcard\_ssl\_chain, and in its place added wildcard\_ssl\_cert\_dir.
+   * ikidns: Added letsencrypt command, which generates wildcard certificates
+     for the domains listed in ikiwiki-hosting.conf, using DNS verification.
+     This needs the python3-certbot-dns-rfc2136 package to be installed,
+     and ikidns to have already been used to configure the dns server.
+   * ikisite letsencrypt: Avoid getting a per-domain cert when a usable
+     wildcard cert exists.
+   * ikisite letsencrypt: When a per-domain cert was already obtained,
+     and a wildcard cert now exists, the per-domain cert will be deleted,
+     and the wildcard cert used.
+ * [ Simon McVittie ]
+   * build: Use `set -e` to trap failure in shell loops
+   * build: Add a `dist` target to the Makefile
+   * Move d/changelog to ./CHANGELOG
+   * Separate upstream releases from Debian packaging
+   * debian/control: Don't use autopkgtest-pkg-perl. Since 0.20160811 the
+     autogenerated test list is not used.
+   * ikiwiki-hosting-web: Depend on real package apache2-suexec-pristine
+     in preference to virtual apache2-suexec
+   * ikiwiki-hosting-web: Add missing dependency on lsb-base
+   * debian/control: Declare compliance with Debian Policy 4.1.4"""]]
\ No newline at end of file

ikidns: Added letsencrypt command
Generates and enables wildcard certificates for the domains listed in
ikiwiki-hosting.conf, using DNS verification. This needs the
python3-certbot-dns-rfc2136 package to be installed, and ikidns to have
already been used to configure the dns server.
This is not complete yet because I hit a rate limit
diff --git a/debian/changelog b/debian/changelog
index 37f9470..900844f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,11 @@ ikiwiki-hosting (0.20161223) UNRELEASED; urgency=medium
     there is no configuration change. ikisite maintaincerts runs it once
     per site, and the resulting many reloads of apache close together
     tended to cause apache to fall over, due to bug #873115.
+  * ikidns: Added letsencrypt command, which generates and enables
+    wildcard certificates for the domains listed in ikiwiki-hosting.conf,
+    using DNS verification. This needs the python3-certbot-dns-rfc2136
+    package to be installed, and ikidns to have already been used to 
+    configure the dns server.
 
  -- Joey Hess <id@joeyh.name>  Wed, 25 Jan 2017 12:35:51 -0400
 
diff --git a/doc/ikidns.mdwn b/doc/ikidns.mdwn
index 8fb86e6..9d111a7 100644
--- a/doc/ikidns.mdwn
+++ b/doc/ikidns.mdwn
@@ -29,9 +29,9 @@ default.
 
 # EXAMPLES
 
-	ikidns setupbind
-
 	scp $(ikidns createkey $newserver) $newserver:/etc/ikiwiki-hosting/keys/dns/
+	
+	ikidns setupbind
 
 # SEE ALSO
 
diff --git a/ikidns b/ikidns
index cebe08d..24f810e 100755
--- a/ikidns
+++ b/ikidns
@@ -118,6 +118,53 @@ sub setupbind {
 	shell("/etc/init.d/bind9", "restart");
 }
 
+sub meta_letsencrypt {
+	required => [qw{}],
+	options => [qw{}],
+	description => "use Lets Encrypt to get wildcard https certificates",
+	section => "utility",
+}
+sub letsencrypt {
+	assert_root();
+	
+	# Use a separate bind key for certbot.
+	my @keys=dns_private_keys("certbot");
+	if (! @keys) {
+		createkey("certbot");
+		setupbind();
+	}
+	my $secret = dns_keysecret("certbot.");
+
+	# This file needs to continue to exist so certbot can use it for
+	# renewals.
+	my $certbot_credfile="$config{keydir}/dns/certbot.credentials";
+	open(OUT, ">", $certbot_credfile) || error "$certbot_credfile: $!";
+	# contains keys, so needs to be only readable by root
+	shell("chown", "root:root", $certbot_credfile);
+	shell("chmod", "600", $certbot_credfile);
+	print OUT "dns_rfc2136_server = 127.0.0.1\n";
+	print OUT "dns_rfc2136_port = 53\n";
+	print OUT "dns_rfc2136_name = certbot.\n";
+	print OUT "dns_rfc2136_secret = $secret\n";
+	print OUT "dns_rfc2136_algorithm = HMAC-MD5\n";
+	close OUT;
+	
+	foreach my $domain (split ' ', $config{domains}) {
+		shell("certbot", "certonly",
+			"--text", "--noninteractive", "--quiet", "--keep-until-expiring",
+			"--agree-tos", "--email=$config{adminemail}",
+			"--dns-rfc2136", 
+			"--dns-rfc2136-credentials", $certbot_credfile,
+			# use ACMEv2 endpoint
+			"--server", "https://acme-v02.api.letsencrypt.org/directory",
+			# request wildcard cert
+                        "--domain=*.$domain");
+	}
+
+	# XXX need to install the certs into place so web server will use
+	# them.
+}
+
 #############################################################################
 
 sub assert_client_haskey {

LE supports wildcard now?
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 20ae63d..ecab24a 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -191,6 +191,8 @@ previously mentioned. --[[anarcat]]
  [lego]: https://github.com/xenolf/lego
 
 
+Note that Let's Encrypt started [supporting wildcard certificates](https://arstechnica.com/information-technology/2017/07/lets-encrypt-to-start-offering-free-wildcard-certificates-for-https/) recently, but only with DNS challenges.. --[[anarcat]]
+
 ---- 
 
 ## how to only enable ssl once a certificate is available

add lego because it supports DNS challenges
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b2d285d..20ae63d 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -64,6 +64,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  * [simp_le][], much simpler implementation in Python ([not in Debian](https://github.com/kuba/simp_le/issues/69))
  * [acme][], root-less, more minimal implementation than the official
    client, in Go ([in Debian stretch and sid](https://tracker.debian.org/pkg/acmetool))
+ * [lego][], root-less, fairly featureful, also [in Debian](https://tracker.debian.org/pkg/lego)
  * [acme-tiny][] is a very small client (~200 lines of python code)
    that aims to be easily audited and to do only one thing well. for
    example, you need to generate your RSA key yourself, which may
@@ -80,6 +81,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  [acme-tiny]: https://github.com/diafygi/acme-tiny/
  [ITP for acmetool]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=817091
  [in Debian stretch and sid]: https://tracker.debian.org/pkg/acme-tiny
+ [lego]: https://github.com/xenolf/lego
 
 Note that I have also considered simply using the `--apache` plugin to just have LE manage all those certs itself. This could conflict with ikiwiki-hosting, but since it runs fairly frequently, it could just win in the end. It's not a great solution for sites managed by the control panel, but for my use case, it could just work. Unforunately, it [parses configs in sites-available instead of just sites-enabled](https://github.com/certbot/certbot/issues/3545) which breaks it for me. --[[anarcat]]
 

Announce 0.20170622
diff --git a/doc/news/version_0.20170622.mdwn b/doc/news/version_0.20170622.mdwn
new file mode 100644
index 0000000..42aa5bd
--- /dev/null
+++ b/doc/news/version_0.20170622.mdwn
@@ -0,0 +1,20 @@
+ikiwiki-hosting 0.20170622 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ [[Joey Hess|joey]] ]
+   * remove, letsnotencrypt: Remove Lets Encrypt renewal file, to avoid
+     the cron job trying to renew deleted sites.
+   * Fix deletion of sites that use https over the web interface.
+   * HTTP Strict Transport Security (HSTS) is enabled for all
+     sites that have `redirect_to_https` set in their configuration.
+     Thanks, Antoine Beaupré.
+   * Improve `ikisite backup` to lock the wiki for a much shorter period of time.
+   * Remove `.ikiwiki/sessions.db` from the ikisite backup, as the file can be
+     rather large, and losing it only means users have to log back in sooner
+     than would otherwise be the case.
+   * ikisite-wrapper: Allow `ikisite enable` to be run via the wrapper.
+     The CGI uses this to update the site config of an already enabled site
+     when enabling eg `redirect_to_https` or adding a DNS alias.
+ * [ [[Simon McVittie|smcv]] ]
+   * debian/copyright: Use preferred https URL for Format
+   * debian/control: Declare compliance with Debian Policy 4.0.0
+   * debian: Update to debhelper compat level 10"""]]

ikisite-wrapper: Allow ikisite enable to be run via the wrapper.
The CGI uses this to update the site config of an already enabled site when
enabling eg redirect_to_https or adding a DNS alias.
This commit was sponsored by Jochen Bartl on Patreon.
diff --git a/IkiWiki/Plugin/ikiwikihosting.pm b/IkiWiki/Plugin/ikiwikihosting.pm
index 5c30ed8..5571fb3 100644
--- a/IkiWiki/Plugin/ikiwikihosting.pm
+++ b/IkiWiki/Plugin/ikiwikihosting.pm
@@ -460,11 +460,14 @@ sub handlechangedsetup {
 	# Drop lock; ikisite takes the lock itself.
 	IkiWiki::unlockwiki();
 
-	# If ipv6 was enabled or disabled, need to refresh dns.
-	IkiWiki::Hosting::getshell("ikisite-wrapper", "enabledns", $config{hostname});
-
 	# Commit any changes to the setup file into the setup branch.
 	IkiWiki::Hosting::getshell("ikisite", "commitsetup", $config{hostname});
+
+	# Re-enable the site for changes to eg, redirect_to_https or dns.
+	# This can't enable any site that's not enabled, since the site has
+	# to be enabled already for this cgi to be run.
+	IkiWiki::Hosting::getshell("ikisite-wrapper", "enable", $config{hostname});
+	
 	exit;
 }
 
diff --git a/debian/changelog b/debian/changelog
index 72f895f..e9b4398 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,9 @@ ikiwiki-hosting (0.20161220) UNRELEASED; urgency=medium
   * Remove .ikiwiki/sessions.db from the ikisite backup, as the file can be
     rather large, and losing it only means users have to log back in sooner
     than would otherwise be the case.
+  * ikisite-wrapper: Allow ikisite enable to be run via the wrapper.
+    The CGI uses this to update the site config of an already enabled site
+    when enabling eg redirect_to_https or adding a DNS alias.
 
  -- Joey Hess <id@joeyh.name>  Wed, 25 Jan 2017 12:35:51 -0400
 
diff --git a/doc/ikisite-wrapper.mdwn b/doc/ikisite-wrapper.mdwn
index 45eb345..39d0f2e 100644
--- a/doc/ikisite-wrapper.mdwn
+++ b/doc/ikisite-wrapper.mdwn
@@ -13,8 +13,8 @@ made suid root, though it is not currently suid by default.
 
 A few ikisite subcommands can be run using the wrapper without any
 authorisation at all. These include: create, branch, list, sitelookup,
-checklock, updatecustomersite, and enabledns. So making the wrapper suid
-allows any user to create a site.
+checklock, updatecustomersite, enabledns, and enable. So making the
+wrapper suid allows any user to create a site.
 
 Other ikisite subcommands can only be run using the wrapper by
 users who specify a nonce in the IKISITE_NONCE environment variable. These
diff --git a/ikisite b/ikisite
index 89c8e13..ac262d7 100755
--- a/ikisite
+++ b/ikisite
@@ -1510,7 +1510,11 @@ sub enable {
 	
 	assert_root();
 	locksite($hostname);
-	assert_wrapper_denied();
+	# Allow the wrapper to enable a site. The CGI for a site uses
+	# this when its configuration is changed; the site is necessarily
+	# already enabled for the CGI to run so this should not let
+	# disabled sites be enabled via the CGI.
+	assert_wrapper_unsafe();
 
 	my $user=username($hostname);
 	my $home=homedir($hostname);
diff --git a/ikisite-wrapper.c b/ikisite-wrapper.c
index 274fff7..a4bde3f 100644
--- a/ikisite-wrapper.c
+++ b/ikisite-wrapper.c
@@ -35,6 +35,7 @@ int main (int argc, char **argv) {
 		    strcmp(argv[1], "updatecustomersite") == 0 ||
 		    strcmp(argv[1], "checksite") == 0 ||
 		    strcmp(argv[1], "enabledns") == 0) {
+		    strcmp(argv[1], "enable") == 0) {
 			/* use a dummy value so ikisite still can tell
 			 * it is being run from the wrapper */
 			nonce="dummy";

HTTP Strict Transport Security (HSTS) is enabled for all sites that have redirect_to_https set in their configuration. Thanks, Antoine Beaupré.
diff --git a/debian/changelog b/debian/changelog
index ab076b7..d79dc65 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,9 @@ ikiwiki-hosting (0.20161220) UNRELEASED; urgency=medium
   * remove, letsnotencrypt: Remove Lets Encrypt renewal file, to avoid
     the cron job trying to renew deleted sites.
   * Fix deletion of sites that use https over the web interface.
+  * HTTP Strict Transport Security (HSTS) is enabled for all
+    sites that have redirect_to_https set in their configuration.
+    Thanks, Antoine Beaupré.
 
  -- Joey Hess <id@joeyh.name>  Wed, 25 Jan 2017 12:35:51 -0400
 
diff --git a/doc/todo/strict_transport_security.mdwn b/doc/todo/strict_transport_security.mdwn
index a832523..8620692 100644
--- a/doc/todo/strict_transport_security.mdwn
+++ b/doc/todo/strict_transport_security.mdwn
@@ -20,3 +20,5 @@ Thanks! --[[anarcat]]
 
 [hsts branch]: https://gitlab.com/anarcat/ikiwiki-hosting/tree/hsts
 [merge it]: https://gitlab.com/anarcat/ikiwiki-hosting/commit/07d443ee33d366c68a57f3d6515ddfbc19147572
+
+> [[merged|done]] --[[Joey]]

some weird issue with the control panel
diff --git a/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn
new file mode 100644
index 0000000..fafbe7e
--- /dev/null
+++ b/doc/bugs/controlpanel_crashes_when_ikisite-wrapper_fails.mdwn
@@ -0,0 +1,41 @@
+If ikisite-wrapper is not suid (which is the default), the command will fail when ran. Or more precisely, it will return nothing.
+
+This will make the following code block crash:
+
+[[!format perl """
+        foreach my $siteinfo (@{IkiWiki::Hosting::yamlgetshell(
+                                  "ikisite-wrapper", "list", "--extended",
+                                  (map { "--admin=$_"} @accounts),
+                                  (map { "--owner=$_"} @accounts),
+                              )}) {
+"""]]
+
+... in controlpanel.pm, because it returns an empty reference. I'm  not sure what to do with this - as I'm not really using the control panel, but I figured this could help:
+
+[[!format diff """
+diff --git a/IkiWiki/Plugin/controlpanel.pm b/IkiWiki/Plugin/controlpanel.pm
+index c55a97d..37981f1 100644
+--- a/IkiWiki/Plugin/controlpanel.pm
++++ b/IkiWiki/Plugin/controlpanel.pm
+@@ -35,11 +35,12 @@ sub sessioncgi ($$) {
+ 
+        my (@owned_sites, @adminned_sites);
+        my $num=0;
+-       foreach my $siteinfo (@{IkiWiki::Hosting::yamlgetshell(
+-                                 "ikisite-wrapper", "list", "--extended",
+-                                 (map { "--admin=$_"} @accounts),
+-                                 (map { "--owner=$_"} @accounts),
+-                             )}) {
++       my $sites = IkiWiki::Hosting::yamlgetshell(
++           "ikisite-wrapper", "list", "--extended",
++           (map { "--admin=$_"} @accounts),
++           (map { "--owner=$_"} @accounts),
++           );
++       foreach my $siteinfo (@{$sites}) {
+                $siteinfo->{cgiurl}=$config{cgiurl};
+                $siteinfo->{num}=$num++;
+ 
+"""]]
+
+
+... no? --[[anarcat]]

HSTS patch
diff --git a/doc/todo/strict_transport_security.mdwn b/doc/todo/strict_transport_security.mdwn
new file mode 100644
index 0000000..a832523
--- /dev/null
+++ b/doc/todo/strict_transport_security.mdwn
@@ -0,0 +1,22 @@
+I noticed a change in my local config during my last ikiwiki-hosting
+upgrade: I had enabled [HSTS][] in my local apache template, to
+prevent downgrade attacks in cases where HTTP to HTTPS redirection is
+enabled.
+
+[HSTS]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
+
+The [[patch]] is trivial, and I encourage you to [merge it][] from
+my [hsts branch][]. I used an arbitrary 6-month delay, but would
+welcome comments on better policies... This was a key part in getting
+my site a [better score][] on the [Mozilla SSL Observatory][]. I made
+other changes at the global level on the server configuration, but
+this one is vhost-specific, so I had to roll it out in the Apache
+template. With the changes, I was able to move from a D- score to A-.
+
+[Mozilla SSL Observatory]: https://observatory.mozilla.org/
+[better score]: https://observatory.mozilla.org/analyze.html?host=anarc.at
+
+Thanks! --[[anarcat]]
+
+[hsts branch]: https://gitlab.com/anarcat/ikiwiki-hosting/tree/hsts
+[merge it]: https://gitlab.com/anarcat/ikiwiki-hosting/commit/07d443ee33d366c68a57f3d6515ddfbc19147572

Announce 0.20161219
diff --git a/doc/news/version_0.20161219.mdwn b/doc/news/version_0.20161219.mdwn
new file mode 100644
index 0000000..d0b0de0
--- /dev/null
+++ b/doc/news/version_0.20161219.mdwn
@@ -0,0 +1,16 @@
+ikiwiki-hosting 0.20161219 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Joey Hess ]
+   * Initial support for Lets Encrypt.
+   * The use\_letsencrypt setting can be set for a site by running
+     ikisite letsencrypt domain, and it will attempt to get the certificate
+     for it using certbot.
+   * ikisite domains: Update certificate using certbot when set of domains
+     changes.
+   * Added ikisite maintaincerts to request/renew Lets Encrypt certs as needed,
+     and added it to the daily cron job.
+   * The files /etc/ikiwiki-hosting/config/$username/domain.{crt,key,chain}
+     are used, when they exist, in preference to the files
+     /etc/ikiwiki-hosting/config/$username/ssl.{key,crt}. This allows
+     a site with multiple domains to have different certificates
+     for them. The Lets Encrypt support uses this."""]]
\ No newline at end of file

update
diff --git a/doc/design/apacheconfig.mdwn b/doc/design/apacheconfig.mdwn
index 6e68397..85523fb 100644
--- a/doc/design/apacheconfig.mdwn
+++ b/doc/design/apacheconfig.mdwn
@@ -22,6 +22,10 @@ Example:
 		AuthUserFile <TMPL_VAR HOME>/apache/htpasswd
 		Require valid-user
 	</Directory>
+	<Directory <TMPL_VAR HOME>/public_html/.well-known>
+	        AuthType None
+		Require all granted
+	</Directory>
 
 Note the use of "+" to add to the default Options, rather than overriding it.
 
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index df73e53..b2d285d 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -308,3 +308,13 @@ slow down site creation etc.
   Or, could make apache-sitealias.tmpl use per-domain cert files. This
   avoids all this complexity. Only the Registration/IP rate limit might be
   a problem with doing this, but it's sufficiently high. (done)
+
+* Sites with a apache.conf.tmpl password protecting the site 
+  will not be able to use letencrypt, unless it's relaxed to let
+  .well-known be accessed w/o password. This can be fixed by
+  adding this to the end of their apache.conf.tmpl file:
+
+	<Directory <TMPL_VAR HOME>/public_html/.well-known>
+		AuthType None
+		Require all granted
+	</Directory>

per-domain ssl cert files
The files /etc/ikiwiki-hosting/config/$username/domain.{crt,key,chain} are
used, when they exist, in preference to the files
/etc/ikiwiki-hosting/config/$username/ssl.{key,crt}. This allows a site
with multiple domains to have different certificates for them.
Change letsencrypt integration to always use per-domain ssl cert files.
This avoids renewal failure modes where one of several domains in a cert
has fallen out of the dns. And it avoids letsencrypt setup failure for a
site if some of its urlaliases are not setup correctly in the dns.
This commit was sponsored by Boyd Stephen Smith Jr. on Patreon.
diff --git a/debian/changelog b/debian/changelog
index 6aedc69..bf14da9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,9 +6,13 @@ ikiwiki-hosting (0.20160812) UNRELEASED; urgency=medium
     for it using certbot.
   * ikisite domains: Update certificate using certbot when set of domains
     changes.
-  * Renewal and retrying failed certificate requests are not yet implemented.
   * Added ikisite maintaincerts to request/renew Lets Encrypt certs as needed,
     and added it to the daily cron job.
+  * The files /etc/ikiwiki-hosting/config/$username/domain.{crt,key,chain}
+    are used, when they exist, in preference to the files
+    /etc/ikiwiki-hosting/config/$username/ssl.{key,crt}. This allows
+    a site with multiple domains to have different certificates
+    for them. The Lets Encrypt support uses this.
 
  -- Joey Hess <id@joeyh.name>  Thu, 13 Oct 2016 16:55:25 -0400
 
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8cd9a37..df73e53 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -225,23 +225,23 @@ an error if the included file doesn't exist. So, something like:
 Add a `use_letsencrypt` config setting in the ikiwiki-hosting plugin.
 (done)
 
-Define a flag file, /etc/ikiwiki-hosting/config/$username/letsencrypt-setup
-which exists when letsencrypt has provided a certificate for a site.
-(done)
+Make /etc/ikiwiki-hosting/config/$username/domain.{crt,key,chain} be
+used for a domain when available, instead of ssl.{crt,key,chain}.
+This allows urlaliases to each get their own letsencrypt cert. (done)
 
 Add `ikisite letsencrypt site`, which first sets `use_letsencrypt`
 and then runs certbot (or whatever, it can be made configurable if
 desired) to try to get a certificate for all of the site's domain(s).
-If certbot succeeds, it symlinks the cert into place, touches the flag
-file, and calls `ikisite enable site` to update the web server config
+If certbot succeeds, it symlinks the cert into place,
+and calls `ikisite enable site` to update the web server config
 to use the cert. (done)
 
 Add `ikisite letsnotencrypt site` which undoes that. (done)
 
 Then add a daily cron job that looks for sites that have `use_letsencrypt`
-set, but don't have the flag file. For each such site, it runs
-`ikisite letsencrypt` to try again to get the cert. 
-(done in `ikisite maintaincerts`)
+set, but don't have letsencrypt certs. (Check that the cert files are
+symlinks to tell). For each such site, it runs `ikisite letsencrypt`
+to try again to get the cert. (done in `ikisite maintaincerts`)
 
 Another cron job can run `certbot renew` to handle all renewals.
 Seems this doesn't need to rejigger the certificate symlinks or the
@@ -307,4 +307,4 @@ slow down site creation etc.
 
   Or, could make apache-sitealias.tmpl use per-domain cert files. This
   avoids all this complexity. Only the Registration/IP rate limit might be
-  a problem with doing this, but it's sufficiently high.
+  a problem with doing this, but it's sufficiently high. (done)
diff --git a/ikisite b/ikisite
index 44701fd..6ccb061 100755
--- a/ikisite
+++ b/ikisite
@@ -973,24 +973,29 @@ sub rootconfig {
 	return $config{ikisite_rootconfigdir}."/".username($hostname);
 }
 
-sub ssl_cert_file {
+sub ssl_file {
+	my $ext=shift;
 	my $hostname=shift;
-	return rootconfig($hostname)."/ssl.crt";
-}
+	my $domain=shift;
+	my $no_fallback=shift;
 
-sub ssl_key_file {
-	my $hostname=shift;
-	return rootconfig($hostname)."/ssl.key";
+	my $perdomain=rootconfig($hostname)."/".$domain.".".$ext;
+	if ($no_fallback || -e $perdomain) {
+		return $perdomain;
+	}
+	else {
+		return rootconfig($hostname)."/ssl.".$ext;
+	}
 }
 
-sub ssl_chain_file {
-	my $hostname=shift;
-	return rootconfig($hostname)."/ssl.chain";
-}
+sub ssl_cert_file { ssl_file("crt", @_) }
+sub ssl_key_file { ssl_file("key", @_) }
+sub ssl_chain_file { ssl_file("chain", @_) }
 
-sub letsencrypt_flag_file {
-	my $hostname=shift;
-	return rootconfig($hostname)."/letsencrypt-setup";
+sub is_letsencrpt_link {
+	my $file=shift;
+	my $link=readlink($file);
+	return (defined $link && $link=~m!/etc/letsencrypt/live!);
 }
 
 sub meta_wikiname {
@@ -1591,74 +1596,9 @@ sub enable {
 	$u=~s://$:/:;
 	my $url=URI->new($u);
 	
-	my $ssl_cert_file=ssl_cert_file($hostname);
-	my $ssl_key_file=ssl_key_file($hostname);
-	my $ssl_chain_file=ssl_chain_file($hostname);
-	# Check that any user provided key file is not password protected,
-	# as that makes apache startup hang. (Also checks that it's valid.)
-	if (-e $ssl_key_file) {
-		if (shell_exitcode("openssl", "rsa",
-				"-in" => $ssl_key_file,
-				"-out" => $ssl_key_file, 
-				"-passin" => "pass:dummy",
-				"-passout" => "pass:dummy") != 0) {
-			$ssl_key_file='';
-			$ssl_cert_file='';
-			$ssl_chain_file='';
-		}
-	}
-	# Use wildcard cert if there is no site specific one, only
-	# if the site is not using its own domain name.
-	if (defined $config{wildcard_ssl_cert} && length $config{wildcard_ssl_cert} &&
-	    defined $config{wildcard_ssl_key} && length $config{wildcard_ssl_key} &&
-	    ! -e $ssl_cert_file && ! -e $ssl_key_file) {
-		my @domains = split(' ', $config{domains});
-		my $wildcard_ok=1;
-		foreach my $h (@hostnames) {
-			my $w_ok=0;
-			foreach my $d (@domains) {
-				if ($h =~ /^.+\.\Q$d\E$/i || $h eq $d) {
-					$w_ok=1;
-				}
-			}
-			$wildcard_ok = $wildcard_ok && $w_ok;
-		}
-		if ($wildcard_ok) {
-			$ssl_cert_file=$config{wildcard_ssl_cert};
-			$ssl_key_file=$config{wildcard_ssl_key};
-			if (defined $config{wildcard_ssl_chain} && length $config{wildcard_ssl_chain}) {
-				$ssl_chain_file=$config{wildcard_ssl_chain};
-			}
-			else {
-				$ssl_chain_file='';
-			}
-		}
-	}
-	my $ssl_enabled=-e $ssl_key_file && -e $ssl_cert_file;
-	my @ssl_template_vars=(
-		ssl_cert_file => $ssl_cert_file,
-		ssl_key_file => $ssl_key_file,
-		ssl_enabled => $ssl_enabled,
-	);
-	if (-e $ssl_chain_file) {
-		push @ssl_template_vars, (
-			ssl_chain_file => $ssl_chain_file,
-			ssl_chain => 1,
-		);
-	}
-
-	# This is the url that alias urls redirect to.
-	my $redirurl=$url;
-	my $httpsredirurl=$url->clone;
-	if ($ssl_enabled) {
-		$httpsredirurl->scheme("https");
-		if (getsetup($hostname, 'redirect_to_https')) {
-			$redirurl->scheme("https");
-			push @ssl_template_vars, (redirect_to_https => 1);
-		}
-	}
-
-	# generate apache config file
+	# write and enable apache config file
+	my $apache_site="ikisite-".$url->host;
+	my $apache_conf_file="/etc/apache2/sites-available/$apache_site.conf";
 	my @apache_template_vars=(
 		suexec => (cgidir($hostname) =~ m!^/var/www!),
 		user => $user,
@@ -1668,16 +1608,8 @@ sub enable {
 		cgidir => cgidir($hostname),
 		logdir => logdir($hostname),
 		source_hostname => "source.$hostname",
-		# Value escaped to prevent leakage
-		# into RewriteEngine regexp.
-		url_escaped => quotemeta($redirurl),
-		https_url_escaped => quotemeta($httpsredirurl),
-		@ssl_template_vars
+		domain_template_vars($hostname, $url->host, $url)
 	);
-
-	# write and enable apache config file
-	my $apache_site="ikisite-".$url->host;

(Diff truncated)
update
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index db63d3b..8cd9a37 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -305,6 +305,6 @@ slow down site creation etc.
   letsencrypt failed, and why. (Worth doing in any case, but I'm not sure
   where to put it in the UI.)
 
-  Or, could make apache-sitealias.tmpl use per-domain cert files. Then
-  enabling letsencrypt for a site with lots of urlaliases would burn
-  through the rate limits faster, but all this complexity would be avoided.
+  Or, could make apache-sitealias.tmpl use per-domain cert files. This
+  avoids all this complexity. Only the Registration/IP rate limit might be
+  a problem with doing this, but it's sufficiently high.

issue also affects renewals
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b5a38cf..db63d3b 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -279,7 +279,6 @@ slow down site creation etc.
   it cannot verify it.
 
   This affects both `ikisite letsencrypt` and `ikisite domains`.
-  Unknown if it affects letsencrypt cert renewal.
 
   `ikisite domains` does not currently ensure that all urlaliases are set
   in the dns. This check could be added, it might cause some problem
@@ -290,7 +289,11 @@ slow down site creation etc.
   `templates/apache-sitealias.tmpl` includes a https configuration.
   That lets redirection from the https urlalias to the main url work.
 
-  This could be fixed by re-running certbot without the urlaliases if it
+  But also, if a cert is issued for domains A and B, and B later falls out
+  of the DNS, renewal of the cert will fail. So this can lead to renewal
+  failures later down the line.
+
+  Partial fix would be re-running certbot without the urlaliases if it
   fails with them. Better to have the main url encrypted even if
   redirection to it cannot be. But, that would leave the
   apache-sitealias.tmpl generating a config that uses the wrong cert for
@@ -299,4 +302,9 @@ slow down site creation etc.
   this case.
 
   Alternatively, could improve the UI so the site admin can see when
-  letsencrypt failed, and why. --[[Joey]]
+  letsencrypt failed, and why. (Worth doing in any case, but I'm not sure
+  where to put it in the UI.)
+
+  Or, could make apache-sitealias.tmpl use per-domain cert files. Then
+  enabling letsencrypt for a site with lots of urlaliases would burn
+  through the rate limits faster, but all this complexity would be avoided.

todo
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index fefd7fe..b5a38cf 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -284,3 +284,19 @@ slow down site creation etc.
   `ikisite domains` does not currently ensure that all urlaliases are set
   in the dns. This check could be added, it might cause some problem
   though.
+
+  Note that this is only a problem because the urlaliases are passed
+  to certbot as --host. That is needed because
+  `templates/apache-sitealias.tmpl` includes a https configuration.
+  That lets redirection from the https urlalias to the main url work.
+
+  This could be fixed by re-running certbot without the urlaliases if it
+  fails with them. Better to have the main url encrypted even if
+  redirection to it cannot be. But, that would leave the
+  apache-sitealias.tmpl generating a config that uses the wrong cert for
+  https, which is bad if some of the urlaliases are accessible in the dns.
+  So, this fix needs a way to prevent that template from using https in
+  this case.
+
+  Alternatively, could improve the UI so the site admin can see when
+  letsencrypt failed, and why. --[[Joey]]

problem
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 6c60ab3..fefd7fe 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -270,3 +270,17 @@ slow down site creation etc.
 > Note: there is already a cron job that runs certbot renew in the Debian package,
 > watch out for dupes... Otherwise: design sounds okay, although I'm not sure 
 > why the flag file is necessary. --[[anarcat]]
+
+## issues
+
+* If a site's urlalias includes some domain that is not in the DNS,
+  or no longer points to the host, this is normally not a problem.
+  But, it will prevent certbot getting a cert for that site, because
+  it cannot verify it.
+
+  This affects both `ikisite letsencrypt` and `ikisite domains`.
+  Unknown if it affects letsencrypt cert renewal.
+
+  `ikisite domains` does not currently ensure that all urlaliases are set
+  in the dns. This check could be added, it might cause some problem
+  though.

decruft
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index f1835a8..6c60ab3 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -266,9 +266,6 @@ restoring from backup, etc) should run `ikisite letsencrypt` at the end
 when the site has `use_letsencrypt` configured. It can take a minute or so
 for letsencrypt to run, so best to do that in the background so as to not
 slow down site creation etc.
-by setting letsencrypt=true in ikiwiki-hosting.conf. Then every
-ikisite command that creates a site (including branching, restoring from
-backup, etc) should run `ikisite letsencrypt` at the end.
 
 > Note: there is already a cron job that runs certbot renew in the Debian package,
 > watch out for dupes... Otherwise: design sounds okay, although I'm not sure 

Merge branch 'master' of ssh://ikiwiki-hosting.branchable.com
Added ikisite maintaincerts to request/renew Lets Encrypt certs as needed, and added it to the daily cron job.
This commit was sponsored by Remy van Elst on Patreon.
diff --git a/debian/changelog b/debian/changelog
index 1c59f36..6aedc69 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,6 +7,8 @@ ikiwiki-hosting (0.20160812) UNRELEASED; urgency=medium
   * ikisite domains: Update certificate using certbot when set of domains
     changes.
   * Renewal and retrying failed certificate requests are not yet implemented.
+  * Added ikisite maintaincerts to request/renew Lets Encrypt certs as needed,
+    and added it to the daily cron job.
 
  -- Joey Hess <id@joeyh.name>  Thu, 13 Oct 2016 16:55:25 -0400
 
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8f2b149..6751cc3 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -236,20 +236,17 @@ If certbot succeeds, it symlinks the cert into place, touches the flag
 file, and calls `ikisite enable site` to update the web server config
 to use the cert. (done)
 
-> Testing this on a system with the jessie certbot backport, certbot
-> fails with "The server experienced an internal error :: Error creating
-> new cert". The log says that the letsencrypt server returned an error
-> 500. --[[Joey]]
-
 Add `ikisite letsnotencrypt site` which undoes that. (done)
 
 Then add a daily cron job that looks for sites that have `use_letsencrypt`
 set, but don't have the flag file. For each such site, it runs
-`ikisite letsencrypt` to try again to get the cert.
+`ikisite letsencrypt` to try again to get the cert. 
+(done in `ikisite maintaincerts`)
 
 Another cron job can run `certbot renew` to handle all renewals.
 Seems this doesn't need to rejigger the certificate symlinks or the
 apache config for renewed sites, so it should be nice and simple.
+(done in `ikisite maintaincerts`)
 
 `ikisite domains` will need to check `use_letsencrypt`. If it's set, and a
 new domain is being added to a site, or a domain removed, it needs to
diff --git a/ikisite b/ikisite
index aa7a38f..fb27785 100755
--- a/ikisite
+++ b/ikisite
@@ -699,6 +699,7 @@ sub list {
 				site_wikiname => getsetup($hostname, "wikiname"),
 				site_created => getsetup($hostname, "created"),
 				site_parent => getsetup($hostname, "parent"),
+				use_letsencrypt => getsetup($hostname, "use_letsencrypt"),
 				isunfinished => $unfinished,
 			};
 		}
@@ -1889,6 +1890,33 @@ sub letsnotencrypt {
 	enable($hostname);
 }
 
+sub meta_maintaincerts {
+	required => [],
+	options => [qw{}],
+	description => "request and renew Lets Encrypt certificates as needed",
+	section => "utility",
+}
+sub maintaincerts {
+	assert_root();
+	assert_wrapper_denied();
+
+	my $inuse=0;
+	foreach my $site (list(extended => 1)) {
+		next if $site->{isunfinished};
+		next unless $site->{use_letsencrypt};
+		$inuse=1;
+		letsencrypt($site->{hostname})
+			unless -e letsencrypt_flag_file($site->{hostname});
+	}
+
+	if ($inuse) {
+		eval { shell("certbot", "renew", "--non-interactive") };
+		eval { shell("apache2ctl", "graceful") };
+	}
+
+	return 1;
+}
+
 sub meta_enabledns {
 	required => [qw{hostname}],
 	options => [qw{}],
diff --git a/ikiwiki-hosting-web-daily b/ikiwiki-hosting-web-daily
index eb6befb..a10f4a0 100755
--- a/ikiwiki-hosting-web-daily
+++ b/ikiwiki-hosting-web-daily
@@ -21,7 +21,10 @@ done
 
 # Reload apache so it will start logging to the new site log files.
 /etc/init.d/apache2 reload
-		
+
+# Request and renew any Lets Encrypt certs as needed.
+ikisite maintaincerts
+
 if [ "$failed" ]; then
 	exit 1
 else

update
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 45cf821..8f2b149 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -236,6 +236,11 @@ If certbot succeeds, it symlinks the cert into place, touches the flag
 file, and calls `ikisite enable site` to update the web server config
 to use the cert. (done)
 
+> Testing this on a system with the jessie certbot backport, certbot
+> fails with "The server experienced an internal error :: Error creating
+> new cert". The log says that the letsencrypt server returned an error
+> 500. --[[Joey]]
+
 Add `ikisite letsnotencrypt site` which undoes that. (done)
 
 Then add a daily cron job that looks for sites that have `use_letsencrypt`
@@ -261,4 +266,6 @@ Once this is tested and working well, it can be made the default,
 by setting `use_letsencrypt` in the autosetup/ files. For that to work,
 every ikisite command that creates a site (including branching,
 restoring from backup, etc) should run `ikisite letsencrypt` at the end
-when the site has `use_letsencrypt` configured.
+when the site has `use_letsencrypt` configured. It can take a minute or so
+for letsencrypt to run, so best to do that in the background so as to not
+slow down site creation etc.

update on status
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 615590a..45cf821 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -223,16 +223,20 @@ an error if the included file doesn't exist. So, something like:
 ## Worked design
 
 Add a `use_letsencrypt` config setting in the ikiwiki-hosting plugin.
+(done)
 
 Define a flag file, /etc/ikiwiki-hosting/config/$username/letsencrypt-setup
 which exists when letsencrypt has provided a certificate for a site.
+(done)
 
 Add `ikisite letsencrypt site`, which first sets `use_letsencrypt`
 and then runs certbot (or whatever, it can be made configurable if
 desired) to try to get a certificate for all of the site's domain(s).
 If certbot succeeds, it symlinks the cert into place, touches the flag
 file, and calls `ikisite enable site` to update the web server config
-to use the cert.
+to use the cert. (done)
+
+Add `ikisite letsnotencrypt site` which undoes that. (done)
 
 Then add a daily cron job that looks for sites that have `use_letsencrypt`
 set, but don't have the flag file. For each such site, it runs
@@ -251,6 +255,7 @@ an alias. Certianly not in the case where the site's primary domain has
 changed. The safe option is certainly to remove the old letsencrypt
 certificate if it fails, and `ikisite enable` will then disable ssl support
 for that site, until the cron job later succeeds in getting a certificate.
+(done)
 
 Once this is tested and working well, it can be made the default,
 by setting `use_letsencrypt` in the autosetup/ files. For that to work,

simplify
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 6cc9390..615590a 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -253,6 +253,7 @@ certificate if it fails, and `ikisite enable` will then disable ssl support
 for that site, until the cron job later succeeds in getting a certificate.
 
 Once this is tested and working well, it can be made the default,
-by setting letsencrypt=true in ikiwiki-hosting.conf. Then every
-ikisite command that creates a site (including branching, restoring from
-backup, etc) should run `ikisite letsencrypt` at the end.
+by setting `use_letsencrypt` in the autosetup/ files. For that to work,
+every ikisite command that creates a site (including branching,
+restoring from backup, etc) should run `ikisite letsencrypt` at the end
+when the site has `use_letsencrypt` configured.

no need to unset redirect_to_https when disabling letsencrypt
That config is only used when there are certificates available.
Also, forgot to enable the site after disabling letsencrypt, in order to
update the apache config..
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 419cdef..6cc9390 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -251,7 +251,6 @@ an alias. Certianly not in the case where the site's primary domain has
 changed. The safe option is certainly to remove the old letsencrypt
 certificate if it fails, and `ikisite enable` will then disable ssl support
 for that site, until the cron job later succeeds in getting a certificate.
-(Also need to unset `redirect_to_https` in this case if it was set before.)
 
 Once this is tested and working well, it can be made the default,
 by setting letsencrypt=true in ikiwiki-hosting.conf. Then every
diff --git a/ikisite b/ikisite
index 5ba6e2b..aa7a38f 100755
--- a/ikisite
+++ b/ikisite
@@ -1878,7 +1878,6 @@ sub letsnotencrypt {
 		message => "letsencrypt disabled",
 		set => [
 			"use_letsencrypt=0",
-			"redirect_to_https=0",
 		],
 	) unless $options{temporary};
 
@@ -1887,8 +1886,7 @@ sub letsnotencrypt {
 	unlink(ssl_key_file($hostname));
 	unlink(ssl_chain_file($hostname));
 	unlink(letsencrypt_flag_file($hostname));
-
-	return 1;
+	enable($hostname);
 }
 
 sub meta_enabledns {

Initial support for Lets Encrypt.
* Initial support for Lets Encrypt.
* The use_letsencrypt setting can be set for a site by running
ikisite letsencrypt domain, and it will attempt to get the certificate
for it using certbot.
* ikisite domains: Update certificate using certbot when set of domains
changes.
* Renewal and retrying failed certificate requests are not yet implemented.
This commit was sponsored by Jeff Goeke-Smith on Patreon.
diff --git a/IkiWiki/Plugin/ikiwikihosting.pm b/IkiWiki/Plugin/ikiwikihosting.pm
index 626b7d2..9a51d88 100644
--- a/IkiWiki/Plugin/ikiwikihosting.pm
+++ b/IkiWiki/Plugin/ikiwikihosting.pm
@@ -76,6 +76,13 @@ sub getsetup () {
 			safe => 1,
 			rebuild => 0,
 		},
+		use_letsencrypt => {
+			type => "boolean",
+			example => 1,
+			description => "use Lets Encrypt to generate http certificate?",
+			safe => 1,
+			rebuild => 0,
+		},
 }
 
 sub sessioncgi ($$) {
diff --git a/debian/changelog b/debian/changelog
index 5c12748..1c59f36 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+ikiwiki-hosting (0.20160812) UNRELEASED; urgency=medium
+
+  * Initial support for Lets Encrypt.
+  * The use_letsencrypt setting can be set for a site by running
+    ikisite letsencrypt domain, and it will attempt to get the certificate
+    for it using certbot.
+  * ikisite domains: Update certificate using certbot when set of domains
+    changes.
+  * Renewal and retrying failed certificate requests are not yet implemented.
+
+ -- Joey Hess <id@joeyh.name>  Thu, 13 Oct 2016 16:55:25 -0400
+
 ikiwiki-hosting (0.20160811) unstable; urgency=medium
 
   * Explicitly remove current working directory from Perl's library
diff --git a/debian/control b/debian/control
index 9784216..fdaad04 100644
--- a/debian/control
+++ b/debian/control
@@ -94,6 +94,7 @@ Depends:
  polygen-data,
  python-docutils,
  uuid,
+ certbot,
  ${misc:Depends},
  ${perl:Depends},
  ${shlibs:Depends},
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 938a4af..419cdef 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -225,7 +225,7 @@ an error if the included file doesn't exist. So, something like:
 Add a `use_letsencrypt` config setting in the ikiwiki-hosting plugin.
 
 Define a flag file, /etc/ikiwiki-hosting/config/$username/letsencrypt-setup
-which exists when letsencrypt is being used for a site.
+which exists when letsencrypt has provided a certificate for a site.
 
 Add `ikisite letsencrypt site`, which first sets `use_letsencrypt`
 and then runs certbot (or whatever, it can be made configurable if
diff --git a/ikisite b/ikisite
index 66622f6..5ba6e2b 100755
--- a/ikisite
+++ b/ikisite
@@ -972,6 +972,26 @@ sub rootconfig {
 	return $config{ikisite_rootconfigdir}."/".username($hostname);
 }
 
+sub ssl_cert_file {
+	my $hostname=shift;
+	return rootconfig($hostname)."/ssl.crt";
+}
+
+sub ssl_key_file {
+	my $hostname=shift;
+	return rootconfig($hostname)."/ssl.key";
+}
+
+sub ssl_chain_file {
+	my $hostname=shift;
+	return rootconfig($hostname)."/ssl.chain";
+}
+
+sub letsencrypt_flag_file {
+	my $hostname=shift;
+	return rootconfig($hostname)."/letsencrypt-setup";
+}
+
 sub meta_wikiname {
 	required => [qw{hostname}],
 	options => [qw{}],
@@ -1208,10 +1228,13 @@ sub domains {
 	
 	# This subcommand can be run from a suid wrapper so inputs
 	# cannot be trusted; check and sanitize.
+	my @newdomains;
 	my @urlalias;
 	my @settings;
 	my $rebuild=0;
 	if (defined $options{external}) {
+		push @newdomains, $options{external};
+
 		if (isinternaldomain($options{external})) {
 			error "$options{external} is a reserved hostname";
 		}
@@ -1256,6 +1279,7 @@ sub domains {
 			"url=http://$hostname",
 			"cgiurl=http://$hostname/ikiwiki.cgi",
 		];
+		push @newdomains, $hostname;
 	}
 	my %seen;
 	foreach my $alias (@{$options{alias}}) {
@@ -1288,6 +1312,12 @@ sub domains {
 		"urlalias=".Dump(\@urlalias),
 	];
 
+	push @newdomains, @urlalias;
+	my @olddomains;
+	foreach my $url (urllist(username($hostname))) {
+		push @olddomains, $url->host;
+	}
+
 	disable($hostname, temporary => 1);
 	changesetup($hostname,
 		rebuild => 0, # not yet; slow
@@ -1297,6 +1327,21 @@ sub domains {
 	);
 	enable($hostname);
 
+	# When there was a change to the set of domains used for a site,
+	# need to either get a new cert from letsencrypt, or temporarily
+	# disable using the old cert. This has to come after the site is
+	# enabled using the new domains, so that letsencrypt can get certs
+	# for them.
+	if (getsetup($hostname, "use_letsencrypt")) {
+		eval q{use Data::Compare};
+		error $@ if $@;
+		my $domainschanged = ! Compare([sort @olddomains], [sort @newdomains]);
+		if ($domainschanged &&
+			! letsencrypt($hostname)) {
+			letsnotencrypt($hostname, temporary => 1);
+		}
+	}
+
 	if ($rebuild) {
 		# A full site rebuild can take a long time for
 		# large sites, so is postponed until after the site's
@@ -1545,9 +1590,9 @@ sub enable {
 	$u=~s://$:/:;
 	my $url=URI->new($u);
 	
-	my $ssl_cert_file=rootconfig($hostname)."/ssl.crt";
-	my $ssl_key_file=rootconfig($hostname)."/ssl.key";
-	my $ssl_chain_file=rootconfig($hostname)."/ssl.chain";
+	my $ssl_cert_file=ssl_cert_file($hostname);
+	my $ssl_key_file=ssl_key_file($hostname);
+	my $ssl_chain_file=ssl_chain_file($hostname);
 	# Check that any user provided key file is not password protected,
 	# as that makes apache startup hang. (Also checks that it's valid.)
 	if (-e $ssl_key_file) {
@@ -1761,6 +1806,91 @@ sub disable {
 	return 1;
 }
 
+sub meta_letsencrypt {
+	required => [qw{hostname}],
+	options => [qw{}],
+	description => "use Lets Encrypt to get https certificate",
+	section => "utility",
+}
+sub letsencrypt {
+	my $hostname=lc(shift);
+
+	assert_root();
+	my $lockfile=locksite($hostname);
+	assert_wrapper_denied();
+
+	changesetup($hostname,
+		rebuild => 0,
+		commit => 1,
+		message => "letsencrypt enabled",
+		set => [
+			"use_letsencrypt=1",
+		],
+	);
+
+	my @domainparams;
+	foreach my $url (urllist(username($hostname))) {
+		push @domainparams, ("--domain=".$url->host);
+	}
+
+	if (shell_exitcode("certbot", "certonly",
+		"--text", "--noninteractive", "--keep-until-expiring",
+		"--agree-tos", "--email=$config{adminemail}",
+		"--webroot", "--webroot-path", destdir($hostname),
+		@domainparams)) {

(Diff truncated)
watch out for dupe cronjobs
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 938a4af..82aa129 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -257,3 +257,7 @@ Once this is tested and working well, it can be made the default,
 by setting letsencrypt=true in ikiwiki-hosting.conf. Then every
 ikisite command that creates a site (including branching, restoring from
 backup, etc) should run `ikisite letsencrypt` at the end.
+
+> Note: there is already a cron job that runs certbot renew in the Debian package,
+> watch out for dupes... Otherwise: design sounds okay, although I'm not sure 
+> why the flag file is necessary. --[[anarcat]]

worked design
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 86dcd29..938a4af 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -137,14 +137,19 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
 > So, this seems a pretty big problem; ikiwiki-hosting sites often use
 > subdomains, and if so, quite likely use more than 5. It could keep a site
 > site http-only until it got a cert. But with 100 sites, that would be nearly
-> half a year of delay! 
+> half a year of delay! (Update: With the new 20 certs/domain/week, that
+> drops to 5 weeks delay.)
+
 > And, what about renewal, wouldn't that be rate limited too?
 > (Update: No, it seems that renewals are not rate limited in the 20
 > certs/domain/week bucket.)
 > 
 > Seems like getting a cert for 100 subdomains under branchable.com (eg),
 > and then moving onto the next cert etc would be the best we could do. But
-> that's a lot more complicated.
+> that's a lot more complicated. In particular, renewal needs to use the
+> same set of 100 domains, and if one of the domains is deleted in the
+> meantime, renewal of those 100 probably won't work, and a new certificate
+> would need to be generated for the 99 remaining.
 > --[[Joey]]
 
 >> Ouch, yes, that is a significant problem for branchable!!! Maybe this should be brought up upstream... I wonder if this couldn't be a way to finance letsencrypt, to have larger providers pay a monthly fee for the service, and bypass those limits. --[[anarcat]]
@@ -210,3 +215,45 @@ an error if the included file doesn't exist. So, something like:
 	IncludeOptional /etc/apache2/sites-available/$domain/*.conf
 
 >> The way I did this here was to generate the cert with the HTTP-only vhost, and only after the cert was generated create the HTTPS vhost... Can't you  have a modified HTTPS vhost generated only *after* the cert is generated? --[[anarcat]]
+
+>>> Yes, I think your approach at the top works; `ikisite enable $domain`
+>>> notices the certs and regenerates an apache config to use them.
+>>> --[[Joey]]
+
+## Worked design
+
+Add a `use_letsencrypt` config setting in the ikiwiki-hosting plugin.
+
+Define a flag file, /etc/ikiwiki-hosting/config/$username/letsencrypt-setup
+which exists when letsencrypt is being used for a site.
+
+Add `ikisite letsencrypt site`, which first sets `use_letsencrypt`
+and then runs certbot (or whatever, it can be made configurable if
+desired) to try to get a certificate for all of the site's domain(s).
+If certbot succeeds, it symlinks the cert into place, touches the flag
+file, and calls `ikisite enable site` to update the web server config
+to use the cert.
+
+Then add a daily cron job that looks for sites that have `use_letsencrypt`
+set, but don't have the flag file. For each such site, it runs
+`ikisite letsencrypt` to try again to get the cert.
+
+Another cron job can run `certbot renew` to handle all renewals.
+Seems this doesn't need to rejigger the certificate symlinks or the
+apache config for renewed sites, so it should be nice and simple.
+
+`ikisite domains` will need to check `use_letsencrypt`. If it's set, and a
+new domain is being added to a site, or a domain removed, it needs to
+delete the flag file and run `ikisite letsencrypt` to (try to) get a new
+certificate. What if that fails? It might be possible to keep using the old
+letsencrypt certificate in some cases, eg when adding
+an alias. Certianly not in the case where the site's primary domain has
+changed. The safe option is certainly to remove the old letsencrypt
+certificate if it fails, and `ikisite enable` will then disable ssl support
+for that site, until the cron job later succeeds in getting a certificate.
+(Also need to unset `redirect_to_https` in this case if it was set before.)
+
+Once this is tested and working well, it can be made the default,
+by setting letsencrypt=true in ikiwiki-hosting.conf. Then every
+ikisite command that creates a site (including branching, restoring from
+backup, etc) should run `ikisite letsencrypt` at the end.

Merge branch 'master' of ssh://ikiwiki-hosting.branchable.com
update
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 36d6837..e1c6fdc 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -127,6 +127,8 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
 > site http-only until it got a cert. But with 100 sites, that would be nearly
 > half a year of delay! 
 > And, what about renewal, wouldn't that be rate limited too?
+> (Update: No, it seems that renewals are not rate limited in the 20
+> certs/domain/week bucket.)
 > 
 > Seems like getting a cert for 100 subdomains under branchable.com (eg),
 > and then moving onto the next cert etc would be the best we could do. But

diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 59cc7eb..ee90180 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -61,7 +61,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
 
  * [dehydrated][], bash-only client that should work all Debian
    releases back to Wheezy (formerly known as letsencrypt.sh, in [Debian jessie, stretch and sid](https://tracker.debian.org/pkg/letsencrypt.sh))
- * [simp_le][], much simpler implementation in Python (not in Debian)
+ * [simp_le][], much simpler implementation in Python ([not in Debian](https://github.com/kuba/simp_le/issues/69))
  * [acme][], root-less, more minimal implementation than the official
    client, in Go ([in Debian stretch and sid](https://tracker.debian.org/pkg/acmetool))
  * [acme-tiny][] is a very small client (~200 lines of python code)

client updates
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 5c5bfba..59cc7eb 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -59,11 +59,11 @@ Potential clients
 
 Finally, note that there is now a fairly [large set of Let's Encrypt clients][], here's a short list (those have not been reviewed or tested for compatiblity with ikiwiki-hosting):
 
- * [letsencrypt.sh][], bash-only client that should work all Debian
-   releases back to Wheezy
+ * [dehydrated][], bash-only client that should work all Debian
+   releases back to Wheezy (formerly known as letsencrypt.sh, in [Debian jessie, stretch and sid](https://tracker.debian.org/pkg/letsencrypt.sh))
  * [simp_le][], much simpler implementation in Python (not in Debian)
  * [acme][], root-less, more minimal implementation than the official
-   client, in Go ([ITP for acmetool][])
+   client, in Go ([in Debian stretch and sid](https://tracker.debian.org/pkg/acmetool))
  * [acme-tiny][] is a very small client (~200 lines of python code)
    that aims to be easily audited and to do only one thing well. for
    example, you need to generate your RSA key yourself, which may
@@ -74,7 +74,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
  [large set of Let's Encrypt clients]: https://github.com/letsencrypt/letsencrypt/wiki/Links
  [simp_le]: https://github.com/kuba/simp_le
- [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
+ [dehydrated]: https://dehydrated.de/
  [acme]: https://github.com/hlandau/acme
  [letsacme]: https://github.com/neurobin/letsacme
  [acme-tiny]: https://github.com/diafygi/acme-tiny/

update on renewals: mostly done, just need to hook this in ikisite now
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 36d6837..5c5bfba 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -81,6 +81,8 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  [ITP for acmetool]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=817091
  [in Debian stretch and sid]: https://tracker.debian.org/pkg/acme-tiny
 
+Note that I have also considered simply using the `--apache` plugin to just have LE manage all those certs itself. This could conflict with ikiwiki-hosting, but since it runs fairly frequently, it could just win in the end. It's not a great solution for sites managed by the control panel, but for my use case, it could just work. Unforunately, it [parses configs in sites-available instead of just sites-enabled](https://github.com/certbot/certbot/issues/3545) which breaks it for me. --[[anarcat]]
+
 Renewals
 --------
 
@@ -104,10 +106,20 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >>>> So the software name changed: it's certbot now. And yes, the renew command seems to work better. There is a `--post-hook` that can restart apache and do various things with certs, but unfortunately prior to 0.7, it runs all the time. Normally, the `--post-hook` is one of those variables that would be saved on renewal, but I haven't tested this because I don't want to have that hook run twice a day. So I'm waiting for this to hit backports before automating this completely, especially since I do not want to diverge from the package's `/etc/cron.d/certbot` cronjob. My test renewal line now looks like:
 >>>>
->>>>     certbot --dry-run renew --post-hook 'service apache2 reload; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'
+>>>>     certbot --dry-run renew --renew-hook 'service apache2 reload; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'
 >>>> 
 >>>> I'll test this again in a few weeks, hopefully when the [new package hits backports](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=826147). --[[anarcat]]
 
+>>>> The software has caught up. To avoid customizing the config file, I had to put the renew-hook in the `/etc/letsencrypt/cli.ini` config file, as such:
+>>>> 
+>>>>     renew-hook = service apache2 reload & etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"
+>>>>
+>>>> Notice the `&` instead of `;` because the latter breaks the LE config file parser. With that, the configured domains are renewed automatically! To add new domains, I just need to repeat steps 3 to 5 above. Note that extra webroots can be specified with:
+>>>>
+>>>>     certbot certonly -w /home/foo -d foo.example.com -w /home/bar -d bar.example.com
+>>>>
+>>>> I.e. the last webroot path is attached to the next domain specified. Next step is to code this in Perl, I guess? --[[anarcat]]
+
 Rate limits
 -----------
 

Announce 0.20160811
diff --git a/doc/news/version_0.20160811.mdwn b/doc/news/version_0.20160811.mdwn
new file mode 100644
index 0000000..4614d05
--- /dev/null
+++ b/doc/news/version_0.20160811.mdwn
@@ -0,0 +1,8 @@
+ikiwiki-hosting 0.20160811 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Explicitly remove current working directory from Perl's library
+     search path, mitigating CVE-2016-1238 (see [[!debbug 588017]])
+   * Debian packaging:
+     - Add a simple autopkgtest for creating and deleting a site
+     - Standards-Version: 3.9.8 (no changes required)
+     - debian/rules: enable compiler hardening"""]]

reload should be enough
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index c3337fc..36d6837 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -98,13 +98,13 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >>> Actually, the `-c /etc/letsenctypt/renewal/$domain.conf` doesn't work at all. The 0.4 client features a new `renew` command that does the right thing (including renewing only if necessary). I tested it here and it seems to work fairly well. My complete update run looks more something like this now: --[[anarcat]]
 
->>>    letsencrypt renew --non-interactive
->>>    git -C /etc add -A letsencrypt
->>>    git commit -m"renew all certs"
+>>>     letsencrypt renew --non-interactive
+>>>     git -C /etc add -A letsencrypt
+>>>     git commit -m"renew all certs"
 
 >>>> So the software name changed: it's certbot now. And yes, the renew command seems to work better. There is a `--post-hook` that can restart apache and do various things with certs, but unfortunately prior to 0.7, it runs all the time. Normally, the `--post-hook` is one of those variables that would be saved on renewal, but I haven't tested this because I don't want to have that hook run twice a day. So I'm waiting for this to hit backports before automating this completely, especially since I do not want to diverge from the package's `/etc/cron.d/certbot` cronjob. My test renewal line now looks like:
 >>>>
->>>>    certbot --dry-run renew --post-hook 'service apache2 restart; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'
+>>>>     certbot --dry-run renew --post-hook 'service apache2 reload; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'
 >>>> 
 >>>> I'll test this again in a few weeks, hopefully when the [new package hits backports](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=826147). --[[anarcat]]
 

some certbot changes
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index d13d7f4..c3337fc 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -5,7 +5,7 @@ it would be great if, as part of the SSL integration, ikiwiki-hosting would call
 First implementation
 --------------------
 
-so far I have done this by hand, using the main client:
+so far I have done this by hand, using the main client (previously called letsencrypt, now called certbot, those instructions may need to be updated):
 
 1. define some handy variables:
 
@@ -18,19 +18,19 @@ so far I have done this by hand, using the main client:
 
    * if you are on Debian sid, stretch or jessie (with backports):
 
-            apt install letsencrypt
+            apt install certbot
 
    * otherwise, run the magic commands:
 
-            git clone https://github.com/letsencrypt/letsencrypt
-            cd letsencrypt
-            ./letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory --help
+            git clone https://github.com/certbot/certbot
+            cd certbot
+            ./cerbot-auto --help
 
 3. request a certificate:
 
         sudo -s
         [ -d .git ] && source venv/bin/activate # only use virtualenv if checking out from git
-        letsencrypt certonly --webroot \
+        certbot certonly --webroot \
           --agree-tos \
           --webroot-path="$webroot" \
           --domains $domain --email $email
@@ -52,7 +52,7 @@ so far I have done this by hand, using the main client:
         service apache2 reload # or restart?
 
 Ikiwiki hosting would need to perform steps 3 to 5, and probably have
-a `Recommends` on letsencrypt. -- [[anarcat]]
+a `Recommends` on certbot. -- [[anarcat]]
 
 Potential clients
 -----------------
@@ -98,9 +98,15 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >>> Actually, the `-c /etc/letsenctypt/renewal/$domain.conf` doesn't work at all. The 0.4 client features a new `renew` command that does the right thing (including renewing only if necessary). I tested it here and it seems to work fairly well. My complete update run looks more something like this now: --[[anarcat]]
 
-    letsencrypt renew --non-interactive
-    git -C /etc add -A letsencrypt
-    git commit -m"renew all certs"
+>>>    letsencrypt renew --non-interactive
+>>>    git -C /etc add -A letsencrypt
+>>>    git commit -m"renew all certs"
+
+>>>> So the software name changed: it's certbot now. And yes, the renew command seems to work better. There is a `--post-hook` that can restart apache and do various things with certs, but unfortunately prior to 0.7, it runs all the time. Normally, the `--post-hook` is one of those variables that would be saved on renewal, but I haven't tested this because I don't want to have that hook run twice a day. So I'm waiting for this to hit backports before automating this completely, especially since I do not want to diverge from the package's `/etc/cron.d/certbot` cronjob. My test renewal line now looks like:
+>>>>
+>>>>    certbot --dry-run renew --post-hook 'service apache2 restart; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'
+>>>> 
+>>>> I'll test this again in a few weeks, hopefully when the [new package hits backports](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=826147). --[[anarcat]]
 
 Rate limits
 -----------

one limit changed
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8f804dd..d13d7f4 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -108,7 +108,7 @@ Rate limits
 Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769), they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:
 
  * 100 Names/Certificate (how many domain names you can include in a single certificate)
- * 5 Certificates per Domain per week
+ * 20 Certificates per Domain per week
  * 500 Registrations/IP address per 3 hours
  * 300 Pending Authorizations/Account per week
 
@@ -130,6 +130,9 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
 >> Ouch, yes, that is a significant problem for branchable!!! Maybe this should be brought up upstream... I wonder if this couldn't be a way to finance letsencrypt, to have larger providers pay a monthly fee for the service, and bypass those limits. --[[anarcat]]
 
 >>> [WP.com switched to LE](https://en.blog.wordpress.com/2016/04/08/https-everywhere-encryption-for-all-wordpress-com-sites/), so there's probably a way around those. --[[anarcat]]
+
+>>> I [asked around](https://news.ycombinator.com/item?id=11460480) and the limits were bumped to 20 certs/domain/week recently. Also, they can tweak the limits upon request. --[[anarcat]
+
 Discussion
 ----------
 

wp.com switched!
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8640b01..8f804dd 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -129,6 +129,7 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
 
 >> Ouch, yes, that is a significant problem for branchable!!! Maybe this should be brought up upstream... I wonder if this couldn't be a way to finance letsencrypt, to have larger providers pay a monthly fee for the service, and bypass those limits. --[[anarcat]]
 
+>>> [WP.com switched to LE](https://en.blog.wordpress.com/2016/04/08/https-everywhere-encryption-for-all-wordpress-com-sites/), so there's probably a way around those. --[[anarcat]]
 Discussion
 ----------
 

renewal fixes
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index f4fc3b8..8640b01 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -29,7 +29,7 @@ so far I have done this by hand, using the main client:
 3. request a certificate:
 
         sudo -s
-        source venv/bin/activate
+        [ -d .git ] && source venv/bin/activate # only use virtualenv if checking out from git
         letsencrypt certonly --webroot \
           --agree-tos \
           --webroot-path="$webroot" \
@@ -96,6 +96,12 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >> True, makes a lot more sense! --[[anarcat]]
 
+>>> Actually, the `-c /etc/letsenctypt/renewal/$domain.conf` doesn't work at all. The 0.4 client features a new `renew` command that does the right thing (including renewing only if necessary). I tested it here and it seems to work fairly well. My complete update run looks more something like this now: --[[anarcat]]
+
+    letsencrypt renew --non-interactive
+    git -C /etc add -A letsencrypt
+    git commit -m"renew all certs"
+
 Rate limits
 -----------
 

use wiki instead of discussion
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 2daf8c5..f4fc3b8 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -72,7 +72,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
 
  [letsencrypt.org gods]: https://letsencrypt.org
  [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
- [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
+ [large set of Let's Encrypt clients]: https://github.com/letsencrypt/letsencrypt/wiki/Links
  [simp_le]: https://github.com/kuba/simp_le
  [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
  [acme]: https://github.com/hlandau/acme

official client in debian backports, acme-tiny in stretch
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index a5899b2..2daf8c5 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -16,7 +16,7 @@ so far I have done this by hand, using the main client:
 
 2. install the letsencrypt client software:
 
-   * if you are on Debian sid, stretch (or when [letsencrypt enters backports][]):
+   * if you are on Debian sid, stretch or jessie (with backports):
 
             apt install letsencrypt
 
@@ -59,13 +59,18 @@ Potential clients
 
 Finally, note that there is now a fairly [large set of Let's Encrypt clients][], here's a short list (those have not been reviewed or tested for compatiblity with ikiwiki-hosting):
 
- * [letsencrypt.sh][], bash-only client that could work in Wheezy
- * [simp_le][], much simpler implementation in Python
- * [acme][], root-less, more minimal implementation than the official client, in Go
- * [acme-tiny][] is a very small client (~200 lines of python code) that aims to be easily audited and to do only one thing well. for example, you need to generate your RSA key yourself (which may actually be a good thing considering how ikiwiki-hosting works)
+ * [letsencrypt.sh][], bash-only client that should work all Debian
+   releases back to Wheezy
+ * [simp_le][], much simpler implementation in Python (not in Debian)
+ * [acme][], root-less, more minimal implementation than the official
+   client, in Go ([ITP for acmetool][])
+ * [acme-tiny][] is a very small client (~200 lines of python code)
+   that aims to be easily audited and to do only one thing well. for
+   example, you need to generate your RSA key yourself, which may
+   actually be a good thing considering how ikiwiki-hosting works
+   ([in Debian stretch and sid][])
 
  [letsencrypt.org gods]: https://letsencrypt.org
- [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
  [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
  [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
  [simp_le]: https://github.com/kuba/simp_le
@@ -73,6 +78,8 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  [acme]: https://github.com/hlandau/acme
  [letsacme]: https://github.com/neurobin/letsacme
  [acme-tiny]: https://github.com/diafygi/acme-tiny/
+ [ITP for acmetool]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=817091
+ [in Debian stretch and sid]: https://tracker.debian.org/pkg/acme-tiny
 
 Renewals
 --------

toc
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index e60378b..a5899b2 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -1,5 +1,7 @@
 it would be great if, as part of the SSL integration, ikiwiki-hosting would call up on the [letsencrypt.org gods][] to install proper certs.
 
+[[!toc]]
+
 First implementation
 --------------------
 
@@ -62,6 +64,19 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  * [acme][], root-less, more minimal implementation than the official client, in Go
  * [acme-tiny][] is a very small client (~200 lines of python code) that aims to be easily audited and to do only one thing well. for example, you need to generate your RSA key yourself (which may actually be a good thing considering how ikiwiki-hosting works)
 
+ [letsencrypt.org gods]: https://letsencrypt.org
+ [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
+ [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
+ [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
+ [simp_le]: https://github.com/kuba/simp_le
+ [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
+ [acme]: https://github.com/hlandau/acme
+ [letsacme]: https://github.com/neurobin/letsacme
+ [acme-tiny]: https://github.com/diafygi/acme-tiny/
+
+Renewals
+--------
+
 Also, renewals need to be processed in some way. It seems that it's possible to just run:
 
     letsencrypt -c /etc/letsenctypt/renewal/$domain.conf --renew-by-default
@@ -74,16 +89,6 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >> True, makes a lot more sense! --[[anarcat]]
 
- [letsencrypt.org gods]: https://letsencrypt.org
- [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
- [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
- [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
- [simp_le]: https://github.com/kuba/simp_le
- [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
- [acme]: https://github.com/hlandau/acme
- [letsacme]: https://github.com/neurobin/letsacme
- [acme-tiny]: https://github.com/diafygi/acme-tiny/
-
 Rate limits
 -----------
 

more answers
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index a08b0af..e60378b 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -166,3 +166,5 @@ Note that IncludeOptional has to be used with a wildcard to avoid it being
 an error if the included file doesn't exist. So, something like:
 
 	IncludeOptional /etc/apache2/sites-available/$domain/*.conf
+
+>> The way I did this here was to generate the cert with the HTTP-only vhost, and only after the cert was generated create the HTTPS vhost... Can't you  have a modified HTTPS vhost generated only *after* the cert is generated? --[[anarcat]]

re-merge rate-limit section, some answers and fixups
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b36b63c..a08b0af 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -66,12 +66,14 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
     letsencrypt -c /etc/letsenctypt/renewal/$domain.conf --renew-by-default
 
-> --renew-by-default renews every time it's run; 
-> --keep-until-expiring instead waits until 30 days before expiry and 
+> `--renew-by-default` renews every time it's run; 
+> `--keep-until-expiring` instead waits until 30 days before expiry and 
 > renews then. I think that's the simpler approach, and the same
 > letsencrypt command line can then both obtain the original cert and renew
 > it. --[[Joey]]
 
+>> True, makes a lot more sense! --[[anarcat]]
+
  [letsencrypt.org gods]: https://letsencrypt.org
  [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
  [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
@@ -92,6 +94,23 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
  * 500 Registrations/IP address per 3 hours
  * 300 Pending Authorizations/Account per week
 
+> That seems to be 5 certificates per domain, not subdomain. 
+> Eg, I asked for tmp.kitenet.net 5 times and now it's not allowing
+> getting a cert for downloads.kitenet.net.
+> 
+> So, this seems a pretty big problem; ikiwiki-hosting sites often use
+> subdomains, and if so, quite likely use more than 5. It could keep a site
+> site http-only until it got a cert. But with 100 sites, that would be nearly
+> half a year of delay! 
+> And, what about renewal, wouldn't that be rate limited too?
+> 
+> Seems like getting a cert for 100 subdomains under branchable.com (eg),
+> and then moving onto the next cert etc would be the best we could do. But
+> that's a lot more complicated.
+> --[[Joey]]
+
+>> Ouch, yes, that is a significant problem for branchable!!! Maybe this should be brought up upstream... I wonder if this couldn't be a way to finance letsencrypt, to have larger providers pay a monthly fee for the service, and bypass those limits. --[[anarcat]]
+
 Discussion
 ----------
 
@@ -119,31 +138,9 @@ golang client ([lego][]), which has the interesting property of
 supporting DNS challenges. The puppet code itself uses the shell script
 previously mentioned. --[[anarcat]]
 
- [puppet implementation]:
- https://bzed.de/post/2016/02/bzed-letsencrypt_puppet_module/
+ [puppet implementation]: https://bzed.de/post/2016/02/bzed-letsencrypt_puppet_module/
  [lego]: https://github.com/xenolf/lego
 
-Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769), they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:
-
- * 100 Names/Certificate (how many domain names you can include in a single certificate)
- * 5 Certificates per Domain per week
- * 500 Registrations/IP address per 3 hours
- * 300 Pending Authorizations/Account per week
-
-> That seems to be 5 certificates per domain, not subdomain. 
-> Eg, I asked for tmp.kitenet.net 5 times and now it's not allowing
-> getting a cert for downloads.kitenet.net.
-> 
-> So, this seems a pretty big problem; ikiwiki-hosting sites often use
-> subdomains, and if so, quite likely use more than 5. It could keep a site
-> site http-only until it got a cert. But with 100 sites, that would be nearly
-> half a year of delay! 
-> And, what about renewal, wouldn't that be rate limited too?
-> 
-> Seems like getting a cert for 100 subdomains under branchable.com (eg),
-> and then moving onto the next cert etc would be the best we could do. But
-> that's a lot more complicated.
-> --[[Joey]]
 
 ---- 
 

expiry
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 469cd1c..b36b63c 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -130,6 +130,21 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
  * 500 Registrations/IP address per 3 hours
  * 300 Pending Authorizations/Account per week
 
+> That seems to be 5 certificates per domain, not subdomain. 
+> Eg, I asked for tmp.kitenet.net 5 times and now it's not allowing
+> getting a cert for downloads.kitenet.net.
+> 
+> So, this seems a pretty big problem; ikiwiki-hosting sites often use
+> subdomains, and if so, quite likely use more than 5. It could keep a site
+> site http-only until it got a cert. But with 100 sites, that would be nearly
+> half a year of delay! 
+> And, what about renewal, wouldn't that be rate limited too?
+> 
+> Seems like getting a cert for 100 subdomains under branchable.com (eg),
+> and then moving onto the next cert etc would be the best we could do. But
+> that's a lot more complicated.
+> --[[Joey]]
+
 ---- 
 
 ## how to only enable ssl once a certificate is available

Merge branch 'master' of ssh://ikiwiki-hosting.branchable.com
update
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b40439a..9b0bd02 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -26,7 +26,7 @@ so far I have done this by hand:
         sudo -s
         source venv/bin/activate
         letsencrypt certonly --webroot \
-          --agree-dev-preview --agree-tos \
+          --agree-tos \
           --webroot-path="$webroot" \
           --domains $domain --email $email
 
@@ -60,7 +60,13 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
 
 Also, renewals need to be processed in some way. It seems that it's possible to just run:
 
-    letsencrypt -c /etc/renewal/$domain.conf --renew-by-default
+    letsencrypt -c /etc/letsenctypt/renewal/$domain.conf --renew-by-default
+
+> --renew-by-default renews every time it's run; 
+> --keep-until-expiring instead waits until 30 days before expiry and 
+> renews then. I think that's the simpler approach, and the same
+> letsencrypt command line can then both obtain the original cert and renew
+> it. --[[Joey]]
 
  [letsencrypt.org gods]: https://letsencrypt.org
  [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
@@ -91,3 +97,28 @@ Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets
  * 5 Certificates per Domain per week
  * 500 Registrations/IP address per 3 hours
  * 300 Pending Authorizations/Account per week
+
+---- 
+
+## how to only enable ssl once a certificate is available
+
+Tip from [[Joey]]:
+
+Letsencrypt has a bit of a chicken and egg problem, in that the http server
+has to be up to get the certificate, but the apache site config file
+has to contain both the http and the https vhost. And the https vhost needs
+to point to cert files not available until letsencrypt has run.
+
+smcv was thinking about dealing with that by generating a temporary
+self-signed cert first. But, I don't like the possibility that a http site
+would come up with such a cert during normal operation.
+
+I found a way around this when adding letsencrypt support to propellor:
+Make the apache site config file contain only the http vhost, and use
+IncludeOptional to include another file which contains the https vhost.
+Generate that file only once letsencrypt has generated the cert.
+
+Note that IncludeOptional has to be used with a wildcard to avoid it being
+an error if the included file doesn't exist. So, something like:
+
+	IncludeOptional /etc/apache2/sites-available/$domain/*.conf

another comment
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8a3b1a9..5e70995 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -101,5 +101,18 @@ Oh, and this could be a [plugin][], not sure if that would make sense, but it's
 >> that seems promising. At the moment only letsencrypt is seems packaged
 >> in debian yet and that's the first bar. --[[Joey]]
 
->>> Agreed as well. Just scratching an itch here... The `acme` client looks interesting, but it's go, which brings a whole set of dependencies in. But I like its philosophy and it could integrate well. Also note that the above instructions fail to take into account the canonical and alias names of the site, which breaks openid logins... Something to fix in my future renewals... --[[anarcat]]
-
+>>> Agreed as well. Just scratching an itch here... The `acme`
+>>> client looks interesting, but it's go, which brings a whole set of
+>>> dependencies in. But I like its philosophy and it could integrate
+>>> well. Also note that the above instructions fail to take into account
+>>> the canonical and alias names of the site, which breaks openid
+>>> logins... Something to fix in my future renewals... --[[anarcat]]
+
+Here's an interesting [puppet implementation][] that mentions another (!)
+golang client ([lego][]), which has the interesting property of
+supporting DNS challenges. The puppet code itself uses the shell script
+previously mentioned. --[[anarcat]]
+
+ [puppet implementation]:
+ https://bzed.de/post/2016/02/bzed-letsencrypt_puppet_module/
+ [lego]: https://github.com/xenolf/lego

restructure
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b40439a..8a3b1a9 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -1,6 +1,9 @@
 it would be great if, as part of the SSL integration, ikiwiki-hosting would call up on the [letsencrypt.org gods][] to install proper certs.
 
-so far I have done this by hand:
+First implementation
+--------------------
+
+so far I have done this by hand, using the main client:
 
 1. define some handy variables:
 
@@ -49,7 +52,8 @@ so far I have done this by hand:
 Ikiwiki hosting would need to perform steps 3 to 5, and probably have
 a `Recommends` on letsencrypt. -- [[anarcat]]
 
-Oh, and this could be a [plugin][], not sure if that would make sense, but it's the way it works on that side of the world.
+Potential clients
+-----------------
 
 Finally, note that there is now a fairly [large set of Let's Encrypt clients][], here's a short list (those have not been reviewed or tested for compatiblity with ikiwiki-hosting):
 
@@ -72,6 +76,21 @@ Also, renewals need to be processed in some way. It seems that it's possible to
  [letsacme]: https://github.com/neurobin/letsacme
  [acme-tiny]: https://github.com/diafygi/acme-tiny/
 
+Rate limits
+-----------
+
+Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769), they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:
+
+ * 100 Names/Certificate (how many domain names you can include in a single certificate)
+ * 5 Certificates per Domain per week
+ * 500 Registrations/IP address per 3 hours
+ * 300 Pending Authorizations/Account per week
+
+Discussion
+----------
+
+Oh, and this could be a [plugin][], not sure if that would make sense, but it's the way it works on that side of the world. --[[anarcat]]
+
 > I would much rather use something small enough to be reviewable, particularly if we're
 > going to have to run it unattended as root; the official Let's Encrypt client is *huge*.
 > We don't have to worry about portability to non-Debian environments or non-Apache
@@ -84,10 +103,3 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 
 >>> Agreed as well. Just scratching an itch here... The `acme` client looks interesting, but it's go, which brings a whole set of dependencies in. But I like its philosophy and it could integrate well. Also note that the above instructions fail to take into account the canonical and alias names of the site, which breaks openid logins... Something to fix in my future renewals... --[[anarcat]]
 
-
-Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769), they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:
-
- * 100 Names/Certificate (how many domain names you can include in a single certificate)
- * 5 Certificates per Domain per week
- * 500 Registrations/IP address per 3 hours
- * 300 Pending Authorizations/Account per week

rate limits details, i personnally hit the 5 certs per domain per week while debugging this
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 4029ae4..b40439a 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -83,3 +83,11 @@ Also, renewals need to be processed in some way. It seems that it's possible to
 >> in debian yet and that's the first bar. --[[Joey]]
 
 >>> Agreed as well. Just scratching an itch here... The `acme` client looks interesting, but it's go, which brings a whole set of dependencies in. But I like its philosophy and it could integrate well. Also note that the above instructions fail to take into account the canonical and alias names of the site, which breaks openid logins... Something to fix in my future renewals... --[[anarcat]]
+
+
+Regarding [rate limits](https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769), they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:
+
+ * 100 Names/Certificate (how many domain names you can include in a single certificate)
+ * 5 Certificates per Domain per week
+ * 500 Registrations/IP address per 3 hours
+ * 300 Pending Authorizations/Account per week

renewals hint
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index d598bdb..4029ae4 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -58,7 +58,9 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  * [acme][], root-less, more minimal implementation than the official client, in Go
  * [acme-tiny][] is a very small client (~200 lines of python code) that aims to be easily audited and to do only one thing well. for example, you need to generate your RSA key yourself (which may actually be a good thing considering how ikiwiki-hosting works)
 
-Also, renewals need to be processed in some way.
+Also, renewals need to be processed in some way. It seems that it's possible to just run:
+
+    letsencrypt -c /etc/renewal/$domain.conf --renew-by-default
 
  [letsencrypt.org gods]: https://letsencrypt.org
  [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018

not necessary: --server https://acme-v01.api.letsencrypt.org/directory
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 5d4a6e3..d598bdb 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -26,7 +26,6 @@ so far I have done this by hand:
         sudo -s
         source venv/bin/activate
         letsencrypt certonly --webroot \
-          --server https://acme-v01.api.letsencrypt.org/directory \
           --agree-dev-preview --agree-tos \
           --webroot-path="$webroot" \
           --domains $domain --email $email

fix formatting
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index b5fa2ce..5d4a6e3 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -4,10 +4,10 @@ so far I have done this by hand:
 
 1. define some handy variables:
 
-    domain=example.com
-    email=nobody@$domain
-    username=w-example
-    webroot=/home/$username/public_html/
+        domain=example.com
+        email=nobody@$domain
+        username=w-example
+        webroot=/home/$username/public_html/
 
 2. install the letsencrypt client software:
 

more alternatives
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index a992166..b5fa2ce 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -57,6 +57,7 @@ Finally, note that there is now a fairly [large set of Let's Encrypt clients][],
  * [letsencrypt.sh][], bash-only client that could work in Wheezy
  * [simp_le][], much simpler implementation in Python
  * [acme][], root-less, more minimal implementation than the official client, in Go
+ * [acme-tiny][] is a very small client (~200 lines of python code) that aims to be easily audited and to do only one thing well. for example, you need to generate your RSA key yourself (which may actually be a good thing considering how ikiwiki-hosting works)
 
 Also, renewals need to be processed in some way.
 
@@ -67,6 +68,8 @@ Also, renewals need to be processed in some way.
  [simp_le]: https://github.com/kuba/simp_le
  [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
  [acme]: https://github.com/hlandau/acme
+ [letsacme]: https://github.com/neurobin/letsacme
+ [acme-tiny]: https://github.com/diafygi/acme-tiny/
 
 > I would much rather use something small enough to be reviewable, particularly if we're
 > going to have to run it unattended as root; the official Let's Encrypt client is *huge*.

make the LE instructions closer to a working script to ease copy-paste
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 2b65d5b..a992166 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -2,6 +2,13 @@ it would be great if, as part of the SSL integration, ikiwiki-hosting would call
 
 so far I have done this by hand:
 
+1. define some handy variables:
+
+    domain=example.com
+    email=nobody@$domain
+    username=w-example
+    webroot=/home/$username/public_html/
+
 2. install the letsencrypt client software:
 
    * if you are on Debian sid, stretch (or when [letsencrypt enters backports][]):
@@ -21,8 +28,8 @@ so far I have done this by hand:
         letsencrypt certonly --webroot \
           --server https://acme-v01.api.letsencrypt.org/directory \
           --agree-dev-preview --agree-tos \
-          --webroot-path=/home/w-example/public_html/ \
-          --domains example.com --email nobody@example.com
+          --webroot-path="$webroot" \
+          --domains $domain --email $email
 
     ... notice how you need to change the two last lines for your
     environment.
@@ -31,13 +38,13 @@ so far I have done this by hand:
       `/etc/letsencrypt/live/example.com`. install it where ikiwiki
       expects it:
 
-        ln -s /etc/letsencrypt/live/example.com/cert.pem /etc/ikiwiki-hosting/config/w-example/ssl.crt
-        ln -s /etc/letsencrypt/live/example.com/fullchain.pem /etc/ikiwiki-hosting/config/w-example/ssl.chain
-        ln -s /etc/letsencrypt/live/example.com/privkey.pem /etc/ikiwiki-hosting/config/w-example/ssl.key
+        ln -s /etc/letsencrypt/live/$domain/cert.pem /etc/ikiwiki-hosting/config/$username/ssl.crt
+        ln -s /etc/letsencrypt/live/$domain/fullchain.pem /etc/ikiwiki-hosting/config/$username/ssl.chain
+        ln -s /etc/letsencrypt/live/$domain/privkey.pem /etc/ikiwiki-hosting/config/$username/ssl.key
 
 5. regenerate the apache configs and restart apache:
 
-        ikisite enable example.com
+        ikisite enable $domain
         service apache2 reload # or restart?
 
 Ikiwiki hosting would need to perform steps 3 to 5, and probably have

announce 0.20160123, fixing a bad bug in 0.20160121 (sorry!)
diff --git a/doc/news/version_0.20160123.mdwn b/doc/news/version_0.20160123.mdwn
new file mode 100644
index 0000000..755642f
--- /dev/null
+++ b/doc/news/version_0.20160123.mdwn
@@ -0,0 +1,4 @@
+ikiwiki-hosting 0.20160123 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Fix the escaping of `{` in HostingAutomator by also escaping the `}`,
+     fixing a regression that broke `ikisite create`"""]]

redo the list and mention aliases
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8000726..2b65d5b 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -45,16 +45,21 @@ a `Recommends` on letsencrypt. -- [[anarcat]]
 
 Oh, and this could be a [plugin][], not sure if that would make sense, but it's the way it works on that side of the world.
 
-Finally, note that there is now a fairly [large set of Let's Encrypt clients][]. For example, there is a [bash-only client][] that could work in Wheezy and a [much simpler implementation in Python][]. Those have not been reviewed or tested for compatiblity with ikiwiki-hosting however.
+Finally, note that there is now a fairly [large set of Let's Encrypt clients][], here's a short list (those have not been reviewed or tested for compatiblity with ikiwiki-hosting):
+
+ * [letsencrypt.sh][], bash-only client that could work in Wheezy
+ * [simp_le][], much simpler implementation in Python
+ * [acme][], root-less, more minimal implementation than the official client, in Go
 
 Also, renewals need to be processed in some way.
 
  [letsencrypt.org gods]: https://letsencrypt.org
  [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
  [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
- [bash-only client]: https://github.com/lukas2511/letsencrypt.sh
  [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
- [much simpler implementation in Python]: https://github.com/kuba/simp_le
+ [simp_le]: https://github.com/kuba/simp_le
+ [letsencrypt.sh]: https://github.com/lukas2511/letsencrypt.sh
+ [acme]: https://github.com/hlandau/acme
 
 > I would much rather use something small enough to be reviewable, particularly if we're
 > going to have to run it unattended as root; the official Let's Encrypt client is *huge*.
@@ -65,3 +70,5 @@ Also, renewals need to be processed in some way.
 >> than overall code size. <https://github.com/hlandau/acme> is one client
 >> that seems promising. At the moment only letsencrypt is seems packaged
 >> in debian yet and that's the first bar. --[[Joey]]
+
+>>> Agreed as well. Just scratching an itch here... The `acme` client looks interesting, but it's go, which brings a whole set of dependencies in. But I like its philosophy and it could integrate well. Also note that the above instructions fail to take into account the canonical and alias names of the site, which breaks openid logins... Something to fix in my future renewals... --[[anarcat]]

comment
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 9ef6f9b..8000726 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -60,3 +60,8 @@ Also, renewals need to be processed in some way.
 > going to have to run it unattended as root; the official Let's Encrypt client is *huge*.
 > We don't have to worry about portability to non-Debian environments or non-Apache
 > web servers, which takes away a lot of the reason to use something so big. --smcv
+
+>> Kind of agreed, but I'm more interested in ameanability to automation
+>> than overall code size. <https://github.com/hlandau/acme> is one client
+>> that seems promising. At the moment only letsencrypt is seems packaged
+>> in debian yet and that's the first bar. --[[Joey]]

create my userpage (copied from ikiwiki.info)
diff --git a/doc/users/smcv.mdwn b/doc/users/smcv.mdwn
new file mode 100644
index 0000000..e9d68cd
--- /dev/null
+++ b/doc/users/smcv.mdwn
@@ -0,0 +1,8 @@
+Website: <https://www.pseudorandom.co.uk/>
+
+Blog: <https://smcv.pseudorandom.co.uk/>
+
+My repository containing ikiwiki-hosting branches:
+
+* gitweb: <http://git.pseudorandom.co.uk/smcv/ikiwiki-hosting.git>
+* anongit: <git://git.pseudorandom.co.uk/git/smcv/ikiwiki-hosting.git>

let's have news and a feed for this wiki too
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 0b27aef..1a240a0 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -3,6 +3,7 @@ interface for [Branchable](http://branchable.com/).
 
 Stuff here:
 
+* [[news]]
 * [[TODO]]
 * [[bugs]]
 * [[security]]
diff --git a/doc/news.mdwn b/doc/news.mdwn
new file mode 100644
index 0000000..7667891
--- /dev/null
+++ b/doc/news.mdwn
@@ -0,0 +1 @@
+[[!inline pages="news/* and !news/*/* and !news/discussion" rss=no atom=yes rootpage="news" show=5]]
diff --git a/doc/news/version_0.20160121.mdwn b/doc/news/version_0.20160121.mdwn
new file mode 100644
index 0000000..cb872eb
--- /dev/null
+++ b/doc/news/version_0.20160121.mdwn
@@ -0,0 +1,15 @@
+ikiwiki-hosting 0.20160121 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ [[Joey Hess|joey]] ]
+   * Fix looping redirection when `redirect_to_https` is set.
+     Thanks, [[Antoine Beaupré|anarcat]].
+   * controlpanel: Display unfocused site buttons with low opacity, but still
+     display them. This is an accessability fix; the old hiding method broken
+     caret browsing and screenreaders.
+ * [ [[Simon McVittie|smcv]] ]
+   * d/control: use https for Homepage
+   * d/control: use pkg-perl autopkgtest setup
+   * Fix "unescaped left brace in regex is deprecated" with Perl 5.22
+   * Normalize packaging through `wrap-and-sort -abst`
+   * Depend on libimage-magick-perl in preference to transitional
+     perlmagick package, similar to [#789221](https://bugs.debian.org/789221) in ikiwiki"""]]

I would prefer not to depend on the (huge) reference Let's Encrypt client
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 0c7a381..9ef6f9b 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -55,3 +55,8 @@ Also, renewals need to be processed in some way.
  [bash-only client]: https://github.com/lukas2511/letsencrypt.sh
  [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
  [much simpler implementation in Python]: https://github.com/kuba/simp_le
+
+> I would much rather use something small enough to be reviewable, particularly if we're
+> going to have to run it unattended as root; the official Let's Encrypt client is *huge*.
+> We don't have to worry about portability to non-Debian environments or non-Apache
+> web servers, which takes away a lot of the reason to use something so big. --smcv

add renewals and other clients.
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 11050a1..0c7a381 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -4,7 +4,7 @@ so far I have done this by hand:
 
 2. install the letsencrypt client software:
 
-   * if you are on Debian sid, stretch (or when [letsencrypt enters backports](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018):
+   * if you are on Debian sid, stretch (or when [letsencrypt enters backports][]):
 
             apt install letsencrypt
 
@@ -43,8 +43,15 @@ so far I have done this by hand:
 Ikiwiki hosting would need to perform steps 3 to 5, and probably have
 a `Recommends` on letsencrypt. -- [[anarcat]]
 
-Oh, and this could be a [plugin](https://github.com/letsencrypt/letsencrypt/wiki/Plugins), not sure if that would make sense, but it's the way it works on that side of the world.
+Oh, and this could be a [plugin][], not sure if that would make sense, but it's the way it works on that side of the world.
+
+Finally, note that there is now a fairly [large set of Let's Encrypt clients][]. For example, there is a [bash-only client][] that could work in Wheezy and a [much simpler implementation in Python][]. Those have not been reviewed or tested for compatiblity with ikiwiki-hosting however.
+
+Also, renewals need to be processed in some way.
 
- [go public on 2015-12-03]: https://letsencrypt.org/2015/11/12/public-beta-timing.html
- [google docs to request a whitelist]: https://docs.google.com/a/letsencrypt.org/forms/d/15Ucm4A20y2rf9gySCTXD6yoLG6Tba7AwYgglV7CKHmM
  [letsencrypt.org gods]: https://letsencrypt.org
+ [letsencrypt enters backports]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018
+ [plugin]: https://github.com/letsencrypt/letsencrypt/wiki/Plugins
+ [bash-only client]: https://github.com/lukas2511/letsencrypt.sh
+ [large set of Let's Encrypt clients]: https://community.letsencrypt.org/t/list-of-client-implementations/2103
+ [much simpler implementation in Python]: https://github.com/kuba/simp_le

beta now public, it's in stretch, and backport underway
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 6ee9863..11050a1 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -2,13 +2,9 @@ it would be great if, as part of the SSL integration, ikiwiki-hosting would call
 
 so far I have done this by hand:
 
-1. register on their beta using the
-   [google docs to request a whitelist][] (shouldn't be necessary
-   after they [go public on 2015-12-03][])
-
 2. install the letsencrypt client software:
 
-   * if you are on Debian sid:
+   * if you are on Debian sid, stretch (or when [letsencrypt enters backports](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809018):
 
             apt install letsencrypt
 

close
diff --git a/doc/bugs/accessability_problem_with_control_panel.mdwn b/doc/bugs/accessability_problem_with_control_panel.mdwn
index 9a07bb9..b451094 100644
--- a/doc/bugs/accessability_problem_with_control_panel.mdwn
+++ b/doc/bugs/accessability_problem_with_control_panel.mdwn
@@ -13,6 +13,6 @@ than accessability, but still seems there should be a way to get both.
 Note that the control panel is designed to work when javascript is
 disabled. The buttons default to visible until javascript hides them.
 
-Possble fix: Instead of totally hiding these buttons, display them with a
-low opacity. So screen readers can still speak them.
+fix: Instead of totally hiding these buttons, display them with a
+low opacity. So screen readers can still speak them. [[done]]
 --[[Joey]]

controlpanel: Display unfocused site buttons with low opacity, but still display them. This is an accessability fix; the old hiding method broken caret browsing and screenreaders.
diff --git a/debian/changelog b/debian/changelog
index 335e885..048ec42 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,9 @@ ikiwiki-hosting (0.20150615) UNRELEASED; urgency=medium
 
   * Fix looping redirection when redirect_to_https is set.
     Thanks, Antoine Beaupré.
+  * controlpanel: Display unfocused site buttons with low opacity, but still
+    display them. This is an accessability fix; the old hiding method broken
+    caret browsing and screenreaders.
 
  -- Joey Hess <id@joeyh.name>  Sat, 21 Nov 2015 14:13:01 -0400
 
diff --git a/doc/bugs/accessability_problem_with_control_panel.mdwn b/doc/bugs/accessability_problem_with_control_panel.mdwn
index 82cc48a..9a07bb9 100644
--- a/doc/bugs/accessability_problem_with_control_panel.mdwn
+++ b/doc/bugs/accessability_problem_with_control_panel.mdwn
@@ -1,7 +1,18 @@
 Report from blind user, was unable to find delete button for sites on the
 control panel.
 
-Probably because the CSS only makes buttons to manage a site visible when
+Probably because the javascript only makes buttons to manage a site visible when
 the mouse is hovering over that site in the list. When I turn on caret
 browsing and use arrow keys to move over sites, I experience the same
-problem. --[[Joey]]
+problem.
+
+The point of the CSS is to reduce visual clutter with the several buttons
+per site.. That is less important
+than accessability, but still seems there should be a way to get both.
+
+Note that the control panel is designed to work when javascript is
+disabled. The buttons default to visible until javascript hides them.
+
+Possble fix: Instead of totally hiding these buttons, display them with a
+low opacity. So screen readers can still speak them.
+--[[Joey]]
diff --git a/templates/controlpanel.tmpl b/templates/controlpanel.tmpl
index f227d2b..f982428 100644
--- a/templates/controlpanel.tmpl
+++ b/templates/controlpanel.tmpl
@@ -33,11 +33,11 @@
 <script type="text/javascript">
 function highlight(elt, class) {
 	elt.bgColor='#e0f5c3';
-	document.getElementById(class).style.display="inline";
+	document.getElementById(class).style.opacity=1.0;
 }
 
 function unhighlight(elt, class) {
-	document.getElementById(class).style.display="none";
+	document.getElementById(class).style.opacity=0.1;
 	elt.bgColor='white';
 }
 
@@ -45,7 +45,7 @@ function unhighlight(elt, class) {
 function hideall() {
 	hideableElements = getElementsByClass('hideable');
 	for (var i = 0; i < hideableElements.length; i++) {
-		hideableElements[i].style.display="none";
+		hideableElements[i].style.opacity=0.1;
 	}
 }
 hook("onload", hideall);

update
diff --git a/doc/bugs/accessability_problem_with_control_panel.mdwn b/doc/bugs/accessability_problem_with_control_panel.mdwn
index 421f877..82cc48a 100644
--- a/doc/bugs/accessability_problem_with_control_panel.mdwn
+++ b/doc/bugs/accessability_problem_with_control_panel.mdwn
@@ -2,4 +2,6 @@ Report from blind user, was unable to find delete button for sites on the
 control panel.
 
 Probably because the CSS only makes buttons to manage a site visible when
-the mouse is hovering over that site in the list. --[[Joey]]
+the mouse is hovering over that site in the list. When I turn on caret
+browsing and use arrow keys to move over sites, I experience the same
+problem. --[[Joey]]

bug report
diff --git a/doc/bugs/accessability_problem_with_control_panel.mdwn b/doc/bugs/accessability_problem_with_control_panel.mdwn
new file mode 100644
index 0000000..421f877
--- /dev/null
+++ b/doc/bugs/accessability_problem_with_control_panel.mdwn
@@ -0,0 +1,5 @@
+Report from blind user, was unable to find delete button for sites on the
+control panel.
+
+Probably because the CSS only makes buttons to manage a site visible when
+the mouse is hovering over that site in the list. --[[Joey]]

close
diff --git a/debian/changelog b/debian/changelog
index c8b873d..335e885 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+ikiwiki-hosting (0.20150615) UNRELEASED; urgency=medium
+
+  * Fix looping redirection when redirect_to_https is set.
+    Thanks, Antoine Beaupré.
+
+ -- Joey Hess <id@joeyh.name>  Sat, 21 Nov 2015 14:13:01 -0400
+
 ikiwiki-hosting (0.20150614) unstable; urgency=medium
 
   [ Joey Hess ]
diff --git a/doc/bugs/ssl_redirection_infinite_loop.mdwn b/doc/bugs/ssl_redirection_infinite_loop.mdwn
index 7b601d9..9a8e772 100644
--- a/doc/bugs/ssl_redirection_infinite_loop.mdwn
+++ b/doc/bugs/ssl_redirection_infinite_loop.mdwn
@@ -56,3 +56,5 @@ index 58e8697..7823b87 100644
 </pre>
 
 works in production in http://anarc.at/ (encrypted with letsencrypt!). -- [[anarcat]]
+
+> [[applied|done]] --[[Joey]]

comment
diff --git a/doc/todo/letsencrypt_support/comment_1_4497b4b6dfd7bcb77bc1e6dac5761f7e._comment b/doc/todo/letsencrypt_support/comment_1_4497b4b6dfd7bcb77bc1e6dac5761f7e._comment
new file mode 100644
index 0000000..305566c
--- /dev/null
+++ b/doc/todo/letsencrypt_support/comment_1_4497b4b6dfd7bcb77bc1e6dac5761f7e._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-11-21T17:38:02Z"
+ content="""
+I definitely want ikiwiki-hosting to support letsencrypt.
+
+It's important that any support includes automated certificate renewals.
+Either by letting the letsencrypt client set things up in a way it can
+later handle renewal of itself, or by having ikiwiki-hosting take care of
+it.
+
+Also, there is rate limiting in the current beta (a few domains per IP or
+something like that), and there may well be rate limiting post-beta. So
+initial request may fail and a site be left in http-only mode. Probably
+calls for a cron job to retry any sites that don't yet have a certificate.
+"""]]

mention letsencrypt plugins
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
index 8bbd4c7..6ee9863 100644
--- a/doc/todo/letsencrypt_support.mdwn
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -35,9 +35,9 @@ so far I have done this by hand:
       `/etc/letsencrypt/live/example.com`. install it where ikiwiki
       expects it:
 
-        ln -s /etc/letsencrypt/live/example.com/cert.pem ikiwiki-hosting/config/w-example/ssl.crt
-        ln -s /etc/letsencrypt/live/example.com/fullchain.pem ikiwiki-hosting/config/w-example/ssl.chain
-        ln -s /etc/letsencrypt/live/example.com/privkey.pem ikiwiki-hosting/config/w-example/ssl.key
+        ln -s /etc/letsencrypt/live/example.com/cert.pem /etc/ikiwiki-hosting/config/w-example/ssl.crt
+        ln -s /etc/letsencrypt/live/example.com/fullchain.pem /etc/ikiwiki-hosting/config/w-example/ssl.chain
+        ln -s /etc/letsencrypt/live/example.com/privkey.pem /etc/ikiwiki-hosting/config/w-example/ssl.key
 
 5. regenerate the apache configs and restart apache:
 
@@ -47,6 +47,8 @@ so far I have done this by hand:
 Ikiwiki hosting would need to perform steps 3 to 5, and probably have
 a `Recommends` on letsencrypt. -- [[anarcat]]
 
+Oh, and this could be a [plugin](https://github.com/letsencrypt/letsencrypt/wiki/Plugins), not sure if that would make sense, but it's the way it works on that side of the world.
+
  [go public on 2015-12-03]: https://letsencrypt.org/2015/11/12/public-beta-timing.html
  [google docs to request a whitelist]: https://docs.google.com/a/letsencrypt.org/forms/d/15Ucm4A20y2rf9gySCTXD6yoLG6Tba7AwYgglV7CKHmM
  [letsencrypt.org gods]: https://letsencrypt.org

letsencrypt todo and instructions/workaround
diff --git a/doc/todo/letsencrypt_support.mdwn b/doc/todo/letsencrypt_support.mdwn
new file mode 100644
index 0000000..8bbd4c7
--- /dev/null
+++ b/doc/todo/letsencrypt_support.mdwn
@@ -0,0 +1,52 @@
+it would be great if, as part of the SSL integration, ikiwiki-hosting would call up on the [letsencrypt.org gods][] to install proper certs.
+
+so far I have done this by hand:
+
+1. register on their beta using the
+   [google docs to request a whitelist][] (shouldn't be necessary
+   after they [go public on 2015-12-03][])
+
+2. install the letsencrypt client software:
+
+   * if you are on Debian sid:
+
+            apt install letsencrypt
+
+   * otherwise, run the magic commands:
+
+            git clone https://github.com/letsencrypt/letsencrypt
+            cd letsencrypt
+            ./letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory --help
+
+3. request a certificate:
+
+        sudo -s
+        source venv/bin/activate
+        letsencrypt certonly --webroot \
+          --server https://acme-v01.api.letsencrypt.org/directory \
+          --agree-dev-preview --agree-tos \
+          --webroot-path=/home/w-example/public_html/ \
+          --domains example.com --email nobody@example.com
+
+    ... notice how you need to change the two last lines for your
+    environment.
+
+4. this will create a certificate in
+      `/etc/letsencrypt/live/example.com`. install it where ikiwiki
+      expects it:
+
+        ln -s /etc/letsencrypt/live/example.com/cert.pem ikiwiki-hosting/config/w-example/ssl.crt
+        ln -s /etc/letsencrypt/live/example.com/fullchain.pem ikiwiki-hosting/config/w-example/ssl.chain
+        ln -s /etc/letsencrypt/live/example.com/privkey.pem ikiwiki-hosting/config/w-example/ssl.key
+
+5. regenerate the apache configs and restart apache:
+
+        ikisite enable example.com
+        service apache2 reload # or restart?
+
+Ikiwiki hosting would need to perform steps 3 to 5, and probably have
+a `Recommends` on letsencrypt. -- [[anarcat]]
+
+ [go public on 2015-12-03]: https://letsencrypt.org/2015/11/12/public-beta-timing.html
+ [google docs to request a whitelist]: https://docs.google.com/a/letsencrypt.org/forms/d/15Ucm4A20y2rf9gySCTXD6yoLG6Tba7AwYgglV7CKHmM
+ [letsencrypt.org gods]: https://letsencrypt.org

there's a bug in the ssl redirection code
diff --git a/doc/bugs/ssl_redirection_infinite_loop.mdwn b/doc/bugs/ssl_redirection_infinite_loop.mdwn
new file mode 100644
index 0000000..7b601d9
--- /dev/null
+++ b/doc/bugs/ssl_redirection_infinite_loop.mdwn
@@ -0,0 +1,58 @@
+this is a [[patch]], really, with full description builtin:
+
+<pre>
+From 8f16b20818a14f27bb18aa3016d5808dd56082c9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= <anarcat@koumbit.org>
+Date: Wed, 18 Nov 2015 23:08:10 -0500
+Subject: [PATCH] fix ssl redirections
+
+it seems the previous redirections were not doing anything, or more
+precisely, they were looping:
+
+    RewriteRule ^/(.*) <TMPL_VAR URL_ESCAPED> [L,R,NE]
+
+... was generting the following rule:
+
+    RewriteRule ^/(.*)  [L,R,NE]
+
+because url_escaped wasn't passed to the template. but even if was, it
+would still do an infinite redirect loop on itself. what it needs is
+https_url_escaped, which wasn't passed either.
+---
+ ikisite                    | 4 ++++
+ templates/apache-site.tmpl | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/ikisite b/ikisite
+index 9197ca3..a847c20 100755
+--- a/ikisite
++++ b/ikisite
+@@ -1621,6 +1621,10 @@ sub enable {
+                cgidir => cgidir($hostname),
+                logdir => logdir($hostname),
+                source_hostname => "source.$hostname",
++               # Value escaped to prevent leakage
++               # into RewriteEngine regexp.
++               url_escaped => quotemeta($redirurl),
++               https_url_escaped => quotemeta($httpsredirurl),
+                @ssl_template_vars
+        );
+
+diff --git a/templates/apache-site.tmpl b/templates/apache-site.tmpl
+index 58e8697..7823b87 100644
+--- a/templates/apache-site.tmpl
++++ b/templates/apache-site.tmpl
+@@ -15,7 +15,7 @@
+
+ <TMPL_IF REDIRECT_TO_HTTPS>
+        RewriteEngine On
+-       RewriteRule ^/(.*) <TMPL_VAR URL_ESCAPED>$1 [L,R,NE]
++       RewriteRule ^/(.*) <TMPL_VAR HTTPS_URL_ESCAPED>$1 [L,R,NE]
+ <TMPL_ELSE>
+        DocumentRoot <TMPL_VAR DESTDIR>
+        <Directory />
+--
+2.1.4
+</pre>
+
+works in production in http://anarc.at/ (encrypted with letsencrypt!). -- [[anarcat]]

describe how the https redirect works
diff --git a/doc/design/apacheconfig.mdwn b/doc/design/apacheconfig.mdwn
index 2e71337..6e68397 100644
--- a/doc/design/apacheconfig.mdwn
+++ b/doc/design/apacheconfig.mdwn
@@ -55,6 +55,10 @@ of the site but not the normal version (enabling HTTP authentication
 for [[!iki plugins/httpauth desc="the httpauth plugin"]], perhaps),
 put it in `/etc/ikiwiki-hosting/config/$username/apache-ssl.conf.tmpl`.
 
+If you want to redirect the plain text (HTTP) site to the SSL version
+(HTTPS), you want to check the `redirect from http to https?` option
+in the config page, or `redirect_to_https` option in the `.setup` file.
+
 ---
 
 Special configuration for the `source.$hostname.$domain` (gitweb)

Added support for emailauth.
Untested!
diff --git a/IkiWiki/Business.pm b/IkiWiki/Business.pm
index 3a37b5c..ff90a8c 100644
--- a/IkiWiki/Business.pm
+++ b/IkiWiki/Business.pm
@@ -52,16 +52,16 @@ sub planinfo ($) {
 # be assumed to exist whether or not it really does.
 # (Maybe this site is being created.)
 sub suggestedplan ($;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $assumesite=shift;
 
 	return undef unless %plans;
 
-	my $currentsites=currentsites($openid, $assumesite);
+	my $currentsites=currentsites($username, $assumesite);
 	my @candidate_plans=sortprice(grep { 
 		$plans{$_}{active} &&
 		$plans{$_}{maxsites} >= $currentsites
-	} upgradeset($openid, 1));
+	} upgradeset($username, 1));
 	return $candidate_plans[0] if @candidate_plans;
 
 	# just in case, fallback to the default plan.
@@ -74,13 +74,13 @@ sub suggestedplan ($;$) {
 # Returns true if the user needs to change from their current plan
 # to cover their sites. (Of if the user has no current plan.)
 sub needchangeplan ($;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $assumesite=shift;
 	
 	return 0 unless %plans;
 
-	my $currentsites=currentsites($openid, $assumesite);
-	my $currentplan=currentplan($openid);
+	my $currentsites=currentsites($username, $assumesite);
+	my $currentplan=currentplan($username);
 	return 1 unless defined $currentplan;
 	if ($plans{$currentplan}{maxsites} < $currentsites) {
 		return 1;
@@ -93,13 +93,13 @@ sub needchangeplan ($;$) {
 # Returns the current price plan for a user.
 # Returns undef if the user is not currently enrolled in a plan.
 sub currentplan ($) {
-	my $openid=shift;
+	my $username=shift;
 	return undef unless %plans;
 
 	eval q{use IkiWiki::Customer};
 	die $@ if $@;
 	
-	my $plan=IkiWiki::Customer::customer_get($openid, "currentplan");
+	my $plan=IkiWiki::Customer::customer_get($username, "currentplan");
 	return $plan;
 }
 
@@ -108,24 +108,25 @@ sub currentplan ($) {
 my $currentsites_cache;
 my $currentsites_cache_owner;
 sub currentsites ($;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $assumesite=shift;
 
 	my @owned;
 	if (defined $currentsites_cache_owner &&
-	    $currentsites_cache_owner eq $openid) {
+	    $currentsites_cache_owner eq $username) {
 		@owned=@$currentsites_cache;
 	}
 	else {
-		# A single user may have multiple openids.
+		# A single user may have multiple openids and emails
+		# used in sites they own.
 		eval q{use IkiWiki::Customer};
 		die $@ if $@;
-		my @openids=IkiWiki::Customer::openid_list($openid);
+		my @accounts=IkiWiki::Customer::account_list($username);
 
 		@owned=split(' ', IkiWiki::Hosting::getshell("ikisite-wrapper",
-			"list", map {"--owner=$_"} @openids));
+			"list", map {"--owner=$_"} @accounts));
 		$currentsites_cache=\@owned;
-		$currentsites_cache_owner=$openid;
+		$currentsites_cache_owner=$username;
 	}
 
 	if (defined $assumesite) {
@@ -138,14 +139,14 @@ sub currentsites ($;$) {
 # Given a user, returns how many additional sites they can make, under
 # their current plan.
 sub sitesavailable ($) {
-	my $openid=shift;
+	my $username=shift;
 	
 	return undef unless %plans;
 
-	my $currentplan=currentplan($openid);
+	my $currentplan=currentplan($username);
 	return 0 unless defined $currentplan;
 	my $maxsites=$plans{$currentplan}{maxsites};
-	my @currentsites=currentsites($openid);
+	my @currentsites=currentsites($username);
 
 	if (@currentsites > $maxsites) {
 		# could happen if user's plan was downgraded, or something
@@ -158,12 +159,12 @@ sub sitesavailable ($) {
 
 # Given a user, returns the set of plans the user could upgrade to.
 sub upgradeset ($;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $includecurrent=shift;
 	
 	return () unless %plans;
 
-	my $currentplan=currentplan($openid);
+	my $currentplan=currentplan($username);
 	if (! defined $currentplan) {
 		return keys %plans;
 	}
@@ -202,12 +203,12 @@ sub monthfrom ($;$) {
 
 # Returns when the next bill should be sent for a user.
 sub nextbilldate ($) {
-	my $openid=shift;
+	my $username=shift;
 	
 	eval q{use IkiWiki::Customer};
 	die $@ if $@;
 
-	my $bill_enddate=IkiWiki::Customer::customer_get($openid, "bill_enddate");
+	my $bill_enddate=IkiWiki::Customer::customer_get($username, "bill_enddate");
 	if (! defined $bill_enddate) {
 		# no bill sent yet; one should be sent immediatly
 		return time;
@@ -220,16 +221,16 @@ sub nextbilldate ($) {
 
 # Checks if it's time to send a reminder bill to a user.
 sub billreminderdue ($) {
-	my $openid=shift;
+	my $username=shift;
 	
 	eval q{use IkiWiki::Customer};
 	die $@ if $@;
 	
-	my $balance=IkiWiki::Customer::customer_get($openid, "balance");
+	my $balance=IkiWiki::Customer::customer_get($username, "balance");
 	if (! defined $balance || $balance <= 0) {
 		return 0;
 	}
-	my $lastbilldate=IkiWiki::Customer::customer_get($openid, "lastbilldate");
+	my $lastbilldate=IkiWiki::Customer::customer_get($username, "lastbilldate");
 	if (! defined $lastbilldate) {
 		# Customer has never been billed, so no reminder is due.
 		return 0;
@@ -244,7 +245,7 @@ sub billreminderdue ($) {
 	
 	return 0 if time < $when; # not due yet
 
-	my $lastreminderdate=IkiWiki::Customer::customer_get($openid, "lastreminderdate");
+	my $lastreminderdate=IkiWiki::Customer::customer_get($username, "lastreminderdate");
 	if (defined $lastreminderdate && $lastreminderdate >= $when) {
 		# Bill reminder has already been sent.
 		return 0;
@@ -266,7 +267,7 @@ sub currmonth () {
 # Invoice ids are of the form: BR-001/2010;
 # the invoice numbering resets at the start of each year.
 sub geninvoiceid ($;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $dry_run=shift;
 	
 	my $invoice = IkiWiki::Customer::dir_get("invoice", "last");
@@ -297,14 +298,14 @@ sub geninvoiceid ($;$) {
 # Invoice BR-XXX/YYYY is stored in the customersite, in the file
 # invoice/YYYY-MM/BR-XXX.
 sub saveinvoice ($$$$) {
-	my $openid=shift;
+	my $username=shift;
 	my $invoicetext=shift;
 	my $dry_run=shift;
 	my $overwrite=shift;
 
 	return if $dry_run;
 	
-	my $invoiceid=IkiWiki::Customer::customer_get($openid, "lastinvoiceid");
+	my $invoiceid=IkiWiki::Customer::customer_get($username, "lastinvoiceid");
 	if (! defined $invoiceid) {
 		die "saveinvoice: failed to find lastinvoiceid";
 	}
@@ -344,37 +345,37 @@ sub saveinvoice ($$$$) {
 # user. Throws an error if the customer should be billed, but cannot
 # due to some problem.
 sub bill ($$;$) {
-	my $openid=shift;
+	my $username=shift;
 	my $template=shift;
 	my $dry_run=shift;

(Diff truncated)
figured out that thing...
diff --git a/doc/todo/git-annex_support.mdwn b/doc/todo/git-annex_support.mdwn
index 70980bf..febcd82 100644
--- a/doc/todo/git-annex_support.mdwn
+++ b/doc/todo/git-annex_support.mdwn
@@ -7,4 +7,78 @@ fatal: unrecognized command 'git-annex-shell '/home/w-...''
 
 The client then sets the `annex-ignore` variable and ignores that remote. And of course we'd also need [ikiwiki itself to support git-annex](https://ikiwiki.info/todo/git-annex_support/) but that's another story - at least allowing uploads would be a nice start.
 
-The workaround, of course, is to set `git-annex-shell` as the command in the `authorized_keys` file instead of `iki-git-shell`... -- [[anarcat]]
+The workaround, of course, is to set `git-annex-shell` as the command in the `authorized_keys` file instead of `iki-git-shell`... but that doesn't quite work because the remote URLs change completely.
+
+So one solution is to exploit the `git-shell-commands` extension of `git-shell`, which allows running arbitrary commands from `git-shell`. Since `git-annex` starts with `git`, it will clear the `iki-git-shell` checks - but it fails in `git-shell` because it's not a recognized git command. To fix this, we need to add the following script in `$HOME/git-shell-commands/git-annex-shell`:
+
+<pre>
+#!/usr/bin/python
+
+import os
+import re
+import shlex
+import sys
+
+try:
+    # original command is like:
+    # "git-annex-shell 'configlist' '/'"
+    # argv is expected to be:
+    # ['git-shell-commands/git-annex-shell', '/home/.../source.git/']
+    # the last argument is the sanitized repo path from iki-git-shell
+    # so parse the original command string into an array safely
+    orig_argv = shlex.split(os.environ['SSH_ORIGINAL_COMMAND'])
+    # construct the command with the original command and the safe repo path
+    cmd = ['git-annex-shell', '-c', orig_argv[1], sys.argv[1]]
+    # if we have more arguments, shove them in (skipping unsafe path)
+    cmd += orig_argv[3:]
+    # restrict git-shell to known commands
+    os.environ['GIT_ANNEX_SHELL_LIMITED'] = 'true'
+    # restrict git-annex to the sanitized repository
+    os.environ['GIT_ANNEX_SHELL_DIRECTORY'] = sys.argv[1]
+    # keep all commands as readonly, disabled
+    #os.environ['GIT_ANNEX_SHELL_READONLY'] = 'true'
+    # split into that new command
+    os.execlp('git-annex-shell', *cmd)
+except Exception as e:
+    print "git-annex-shell wrapper improperly called: %s" % e
+</pre>
+
+This will not work out of the box with `iki-git-shell` because the C code garbles the `SSH_ORIG_COMMAND` with `strtok`. The following patch is also necessary to carry the command down below:
+
+<pre>
+diff --git a/iki-git-shell.c b/iki-git-shell.c
+index 70250ad..37639a2 100644
+--- a/iki-git-shell.c
++++ b/iki-git-shell.c
+@@ -74,6 +74,10 @@ int main (int argc, char **argv) {
+                fprintf(stderr, "error: SSH_ORIGINAL_COMMAND not set\n");
+                exit(1);
+        }
++       if (asprintf(&command, command) == -1) {
++               perror("asprintf");
++               exit(1);
++       }
+
+        s=strtok(command, " -"); /* handle "git-" and "git " */
+        if (! s) {
+</pre>
+
+That way the tokenizer operates on a copy of the string instead of garbling the environment directly.
+
+Now, I know that:
+
+ 1. this is clunky
+ 2. it's python (heretic! burn! burn!)
+ 3. there's more comments than code (but I took a while to figure that stuff out, so better to share)
+ 4. it doesn't solve git-annex support in ikiwiki (ie. the objects won't get pushed to the source repo)
+ 5. it's 1h30AM on a friday
+
+But:
+
+ 1. it's a start!
+ 2. it works (ie. it will drop keys, share configs, etc)
+ 3. it should be fairly secure
+
+Your feedback would be greatly appreciated here. At the very least I think the patch on iki-git-shell can't hurt, unless hiding the original git command was deliberate. 
+
+Thanks! -- [[anarcat]]

feature request, really...
diff --git a/doc/todo/git-annex_support.mdwn b/doc/todo/git-annex_support.mdwn
new file mode 100644
index 0000000..70980bf
--- /dev/null
+++ b/doc/todo/git-annex_support.mdwn
@@ -0,0 +1,10 @@
+It would be great to support [git-annex](https://git-annex.branchable.com/) in ikiwiki-hosting. One of the things that would need to change would be the `iki-git-shell` command, which currently doesn't allow `git-annex-shell` to run, which breaks `git-annex`. I tried setting the `annex-shell` variable on the client side to `git annex-shell` to try to workaround the issue, but it still fails with:
+
+<pre>
+fatal: unrecognized command 'git-annex-shell '/home/w-...''
+...
+</pre>
+
+The client then sets the `annex-ignore` variable and ignores that remote. And of course we'd also need [ikiwiki itself to support git-annex](https://ikiwiki.info/todo/git-annex_support/) but that's another story - at least allowing uploads would be a nice start.
+
+The workaround, of course, is to set `git-annex-shell` as the command in the `authorized_keys` file instead of `iki-git-shell`... -- [[anarcat]]

bug report
diff --git a/doc/bugs/stale_git_lockfile_cleanup_on_boot.mdwn b/doc/bugs/stale_git_lockfile_cleanup_on_boot.mdwn
new file mode 100644
index 0000000..061edc9
--- /dev/null
+++ b/doc/bugs/stale_git_lockfile_cleanup_on_boot.mdwn
@@ -0,0 +1,5 @@
+A server crash or unclean shutdown can result in .git/index.lck files
+in sites, which prevent further commits.
+
+At startup, ikiwiki-hosting could find such files and remove. It would
+need to do it before the webserver is started to avoid races. --[[Joey]] 

fix typos, document apache-{ssl,source}.conf.tmpl
diff --git a/doc/design/apacheconfig.mdwn b/doc/design/apacheconfig.mdwn
index ec9bb38..2e71337 100644
--- a/doc/design/apacheconfig.mdwn
+++ b/doc/design/apacheconfig.mdwn
@@ -5,7 +5,7 @@ It can be useful to tweak apache settings for a single site. To allow this,
 use `/etc/ikiwiki-hosting/config/$username/apache.conf.tmpl`
 
 This is an apache2 config fragment, that, if present, is inserted into the
-site's generated apache config file by `ikisite enable`. Remeber to run
+site's generated apache config file by `ikisite enable`. Remember to run
 `ikisite enable` if modifying it.
 
 It is inserted inside the `<VirtualHost>` tag in the apache config file,
@@ -34,7 +34,7 @@ for a given site, this file can be used to enable it.
 
 ---
 
-To enable SSL, just install the ssl cerificate to
+To enable SSL, just install the ssl certificate to
 `/etc/ikiwiki-hosting/config/$username/ssl.crt`
 and the key to 
 `/etc/ikiwiki-hosting/config/$username/ssl.key`.
@@ -49,3 +49,14 @@ if the CA need to provide additional certificate chain material.
 Note that it's up to you to configure apache to use SNI if using SSL
 for multiple virtual hosts on a single IP. See
 <http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI>
+
+If you want some Apache configuration to be applied to the SSL version
+of the site but not the normal version (enabling HTTP authentication
+for [[!iki plugins/httpauth desc="the httpauth plugin"]], perhaps),
+put it in `/etc/ikiwiki-hosting/config/$username/apache-ssl.conf.tmpl`.
+
+---
+
+Special configuration for the `source.$hostname.$domain` (gitweb)
+virtual host can be provided too, in
+`/etc/ikiwiki-hosting/config/$username/apache-source.conf.tmpl`.

Improved method of disabling mod_userdir. (smcv)
diff --git a/debian/changelog b/debian/changelog
index a10b890..077fdea 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,6 +20,7 @@ ikiwiki-hosting (0.20140228) UNRELEASED; urgency=medium
   * Deal with apache 2.4 upgrade, including making sites-available files
     with the .conf extension. Remains compatable with apache 2.2.
     (smcv) Closes: #744789
+  * Improved method of disabling mod_userdir. (smcv)
 
  -- Joey Hess <joeyh@debian.org>  Fri, 07 Mar 2014 11:38:41 -0400
 
diff --git a/doc/todo/do_not_enable_mod__95__userdir_just_so_we_can_disable_it.mdwn b/doc/todo/do_not_enable_mod__95__userdir_just_so_we_can_disable_it.mdwn
index fb47c62..ce713c0 100644
--- a/doc/todo/do_not_enable_mod__95__userdir_just_so_we_can_disable_it.mdwn
+++ b/doc/todo/do_not_enable_mod__95__userdir_just_so_we_can_disable_it.mdwn
@@ -25,3 +25,5 @@ My `ready/userdir` [[branch|patch]] fixes that.
 >>   vhosts; new installations won't need to load it at all.
 >>
 >> --[[smcv]]
+
+>>> [[merged|done]] --[[Joey]]