Is it necessary to have separate virtualhost blocks for the http and https versions of each site? or is there some way to avoid the duplication?
Unlike for example a server block in nginx that can support both http and https definitions (each on a different port) in a single server block the Apache VirtualHost only has a toggle.
SSLEngine directive switches TLS either on or off for the entire VirtualHost.
SSLEngine optional setting is more a curiosity and not a valid production option to support both plain http and https from a single VirtualHost block. )
You will get protocol errors when attempting to connect with plain http to a Apache https IP-address & port combination or vice-versa when using https on a plain http port.
Based on my testing, it appears it is necessary to have separate virtualhost blocks for the default virtualhost on each port, but secondary virtualhosts can use the same virtualhost block for both plain http and https.
However these secondary virtual hosts must be specified with an explicit list of ports, e.g. *:80 *:443, not with just a plain wildcard.