<?xml version="1.0"?>
<!-- name="generator" content="blojsom v2.28" -->
<rss version="2.0" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <channel>
        <title>An Experiment in Bitrot</title>
        <link>https://blojsom.audiodude.xyz/blojsom/blog/default/</link>
        <description>Can we blog with sotware from 2006? How hard is it?</description>
        <language>en</language>
        <image>
            <url>https://blojsom.audiodude.xyz/blojsom/favicon.ico</url>
            <title>An Experiment in Bitrot</title>
            <link>https://blojsom.audiodude.xyz/blojsom/blog/default/</link>
        </image>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<generator>blojsom v2.28</generator>
		<managingEditor>audiodude@gmail.com</managingEditor>
		<webMaster>audiodude@gmail.com</webMaster>
		<pubDate>Sat, 5 Sep 2026 00:59:52 +0000</pubDate>

                <item>
            <title>Deploying blojsom 2.28 (2006) on a modern host, 2026</title>
            <link>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Deploying-blojsom-2-28-2006-on-a-modern-host-2026.html</link>
            <description>&lt;p&gt;Live instance: &lt;a href=&quot;https://blojsom-production.up.railway.app/blojsom/blog/&quot;&gt;https://blojsom-production.up.railway.app/blojsom/blog/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Verdict up front: &lt;strong&gt;very possible, comfortably a weekend project, realistically an afternoon.&lt;/strong&gt; Zero Java source changes. Zero build-file changes. Zero changes to any file the project shipped. Everything added is three new files in &lt;code&gt;deploy/&lt;/code&gt; plus a &lt;code&gt;Dockerfile&lt;/code&gt;, and every &quot;change&quot; is either container plumbing or a value the original INSTALL instructions told you to edit by hand anyway.&lt;/p&gt;
&lt;p&gt;Wall-clock for this run: roughly 25 minutes from &lt;code&gt;git clone&lt;/code&gt; to a post written through the live admin UI surviving a container restart, including two dead ends noted below.&lt;/p&gt;
&lt;h3&gt;What blojsom 2.28 is, technically&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Servlet 2.3 webapp, Java source/target 1.4, built with Ant (&lt;code&gt;build.xml&lt;/code&gt;, no Maven, no downloads: every dependency is a jar checked into &lt;code&gt;war/WEB-INF/lib&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;No database. Entries are files on disk under &lt;code&gt;blog-home&lt;/code&gt;; comments, trackbacks, and metadata are sibling dot-directories. Config is &lt;code&gt;.properties&lt;/code&gt; files under &lt;code&gt;WEB-INF/&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Velocity 1.4 templates, log4j 1.2.8, commons-*, xmlrpc 1.2. All pre-2006.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;That profile is &lt;em&gt;why&lt;/em&gt; this is easy: a self-contained, dependency-vendored, file-backed WAR is close to the best case for resurrecting old Java.&lt;/p&gt;
&lt;h3&gt;The steps&lt;/h3&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Find the right tree.&lt;/strong&gt; The GitHub repo is an SVN dump. 2.28 lives at &lt;code&gt;branches/blojsom-2_28-final/blojsom-2.0/&lt;/code&gt; (the &lt;code&gt;tags/&lt;/code&gt; directory stops at 2.19; later releases are under &lt;code&gt;branches/&lt;/code&gt;). Trunk is 3.x, a different animal (Spring + Hibernate + SQL).&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Pick a JDK that still compiles &lt;code&gt;-source 1.4&lt;/code&gt;.&lt;/strong&gt; JDK 9+ removed it (&lt;code&gt;javac&lt;/code&gt; 9 minimum is 6, current is 8). JDK 8 accepts it with warnings. So: &lt;code&gt;eclipse-temurin:8-jdk&lt;/code&gt;. &lt;code&gt;apt-get install ant&lt;/code&gt;, &lt;code&gt;ant war&lt;/code&gt;. Build succeeds first try, 2 seconds, four &quot;obsolete option&quot; warnings. Output: &lt;code&gt;distro/blojsom.war&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Pick a servlet container that still speaks &lt;code&gt;javax.servlet&lt;/code&gt;.&lt;/strong&gt; Tomcat 10+ is &lt;code&gt;jakarta.*&lt;/code&gt; and will not load this WAR (Tomcat 10&#39;s auto-migration converter would probably work, but that is a change). Tomcat 9.0.x is still maintained and runs on JDK 8: &lt;code&gt;tomcat:9.0-jdk8-temurin&lt;/code&gt;. Drop the WAR in &lt;code&gt;webapps/&lt;/code&gt;, done. The &lt;code&gt;web.xml&lt;/code&gt; is DTD-era 2.3 and Tomcat 9 accepts it without complaint.&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Give it somewhere to write.&lt;/strong&gt; &lt;code&gt;blog.properties&lt;/code&gt; ships with &lt;code&gt;blog-home=/change/me/please/&lt;/code&gt;. On a PaaS the container filesystem is ephemeral, so this has to be a mounted volume. Railway: one volume mounted at &lt;code&gt;/data&lt;/code&gt;, &lt;code&gt;blog-home=/data/blog/&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Tell it its own URL.&lt;/strong&gt; blojsom builds absolute links (including the admin login form&#39;s &lt;code&gt;action&lt;/code&gt;) from &lt;code&gt;blog-base-url&lt;/code&gt; / &lt;code&gt;blog-url&lt;/code&gt; in &lt;code&gt;blog.properties&lt;/code&gt;. Wrong value = admin login posts to &lt;code&gt;localhost:8080&lt;/code&gt; and fails silently. &lt;code&gt;deploy/entrypoint.sh&lt;/code&gt; rewrites these at boot from &lt;code&gt;BLOJSOM_BASE_URL&lt;/code&gt; (falls back to Railway&#39;s &lt;code&gt;RAILWAY_PUBLIC_DOMAIN&lt;/code&gt;).&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Create an admin user.&lt;/strong&gt; Two files, not one: Both are done by the entrypoint from &lt;code&gt;BLOJSOM_ADMIN_PASSWORD&lt;/code&gt;.&lt;ul&gt;&lt;li&gt;&lt;code&gt;authorization.properties&lt;/code&gt;: &lt;code&gt;admin=&amp;lt;md5 hex&amp;gt;&lt;/code&gt; with &lt;code&gt;use-encrypted-passwords=true&lt;/code&gt; and &lt;code&gt;digest-algorithm=MD5&lt;/code&gt; added to &lt;code&gt;blog.properties&lt;/code&gt; (plaintext also works; the file format supports either).&lt;/li&gt;&lt;li&gt;&lt;code&gt;permissions.properties&lt;/code&gt;: &lt;code&gt;admin=*&lt;/code&gt;. Without this you can log in but every admin page says &quot;You do not have permission&quot;. The shipped file only grants &lt;code&gt;default=*&lt;/code&gt;, and &lt;code&gt;default&lt;/code&gt; is not a user in the shipped &lt;code&gt;authorization.properties&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Listen on &lt;code&gt;$PORT&lt;/code&gt;.&lt;/strong&gt; Tomcat&#39;s &lt;code&gt;server.xml&lt;/code&gt; hardcodes 8080; entrypoint &lt;code&gt;sed&lt;/code&gt;s it. Railway also lets you pin the target port to 8080 on the domain, which is what I did, so this is belt-and-braces.&lt;/li&gt;&lt;/ol&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Railway plumbing:&lt;/strong&gt; project, empty service, volume at &lt;code&gt;/data&lt;/code&gt;, two env vars, generate a domain, &lt;code&gt;railway up&lt;/code&gt; from this directory (25 MB upload; the Dockerfile is autodetected). First build+deploy about 60 seconds.&lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Dead ends hit&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;unzip&lt;/code&gt; is not in the Tomcat image.&lt;/strong&gt; Used &lt;code&gt;jar xf&lt;/code&gt; (present, since the image has a JDK) to explode the WAR. Exploding rather than dropping the &lt;code&gt;.war&lt;/code&gt; in was a choice: blojsom&#39;s admin plugins write back into &lt;code&gt;WEB-INF/default/*.properties&lt;/code&gt; at runtime, which only works on an exploded layout.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ant war&lt;/code&gt; deletes &lt;code&gt;war/WEB-INF/default/templates&lt;/code&gt; after jarring&lt;/strong&gt;, so you cannot just &lt;code&gt;COPY&lt;/code&gt; the &lt;code&gt;war/&lt;/code&gt; directory out of the build stage; you must take &lt;code&gt;distro/blojsom.war&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Shipped &lt;code&gt;authorization.properties&lt;/code&gt; has no trailing newline.&lt;/strong&gt; A naive &lt;code&gt;echo &amp;gt;&amp;gt; file&lt;/code&gt; glues &lt;code&gt;admin=...&lt;/code&gt; onto the last comment line. Fixed in &lt;code&gt;setprop&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The permissions file&lt;/strong&gt; (step 6). Not mentioned anywhere obvious; found by grepping for the error string.&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;What does &lt;em&gt;not&lt;/em&gt; work, or is degraded, and was left alone&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Weather plugin&lt;/strong&gt; logs a 403 at boot: it fetches &lt;code&gt;&lt;a href=&quot;http://www.nws.noaa.gov/data/current_obs/null.xml&quot;&gt;http://www.nws.noaa.gov/data/current_obs/null.xml&lt;/a&gt;&lt;/code&gt;. Harmless, unconfigured plugin phoning a dead URL.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ping URLs&lt;/strong&gt; (&lt;code&gt;rpc.weblogs.com&lt;/code&gt;, &lt;code&gt;rpc.pingomatic.com&lt;/code&gt;) on publish: pingomatic still exists, weblogs.com does not. Unchecked the &quot;ping&quot; box when posting; leaving it checked just adds a slow timeout to publishing.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Outbound email&lt;/strong&gt; (comment notifications) points at &lt;code&gt;smtp-server=localhost&lt;/code&gt; in &lt;code&gt;web.xml&lt;/code&gt;. No SMTP in the container; &lt;code&gt;blog-email-enabled=false&lt;/code&gt; by default so nothing breaks.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Admin-UI edits to blog settings&lt;/strong&gt; (name, description, plugins) land in &lt;code&gt;WEB-INF/default/*.properties&lt;/code&gt; &lt;em&gt;inside the container image&lt;/em&gt;, not on the volume. They survive restarts but not redeploys. Posts, comments, and trackbacks are on the volume and survive both (verified by restart). Fixing this properly means pointing &lt;code&gt;blojsom-configuration-base-directory&lt;/code&gt; off-WAR, which blojsom 2.x resolves relative to the servlet context, so it would be an actual change; skipped.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Security.&lt;/strong&gt; This is 2006 code: MD5 passwords, no CSRF tokens, a comment form open to the internet, an XML-RPC endpoint (&lt;code&gt;/blojsom/xmlrpc/&lt;/code&gt;) and Atom API on by default, log4j 1.2.8 (not the log4shell branch, but unmaintained). Do not put anything you care about behind that admin password. Fine for a demo, not fine for a real blog without at least fronting it with something.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;HTTPS.&lt;/strong&gt; Railway terminates TLS at the edge; Tomcat sees plain HTTP. blojsom does not care because it builds URLs from &lt;code&gt;blog-base-url&lt;/code&gt;, which we set to &lt;code&gt;&lt;a href=&quot;https://...&quot;&gt;https://...&lt;/a&gt;&lt;/code&gt;. If you ever set that to &lt;code&gt;http://&lt;/code&gt;, browsers will block the mixed-content form posts.&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Could a normal person do this in a weekend?&lt;/h3&gt;
&lt;p&gt;Yes, with these caveats about who &quot;a normal person&quot; is:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Someone who has run Docker before and knows what a WAR is:&lt;/strong&gt; an afternoon. The whole thing is one Dockerfile and a shell script; the only genuine research is &quot;which JDK / which Tomcat&quot;, and both answers are one search away.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Someone who has never touched Java:&lt;/strong&gt; still a weekend, but a frustrating one. The failure modes (silent redirect to &lt;code&gt;localhost:8080&lt;/code&gt; on login, the permissions file, the templates directory being deleted after the WAR is built) produce no useful error messages. Expect to read &lt;code&gt;web.xml&lt;/code&gt;, &lt;code&gt;blog.properties&lt;/code&gt;, and one Java file.&lt;/li&gt;&lt;li&gt;**Someone who wants to do it &lt;em&gt;without&lt;/em&gt; Docker,** on a classic VPS: also fine, arguably closer to what the 2006 INSTALL doc assumed. &lt;code&gt;apt install openjdk-8-jdk tomcat9&lt;/code&gt; on Debian/Ubuntu, &lt;code&gt;ant war&lt;/code&gt;, copy the WAR. Same config edits, done by hand.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;What would push it past a weekend: wanting Tomcat 10/11 (jakarta migration), wanting a supported JDK (17/21 will run the compiled classes fine; it is only the &lt;em&gt;compile&lt;/em&gt; step that needs 8, so you could build on 8 and run on 21 with Tomcat 9), or wanting blojsom &lt;strong&gt;3.x&lt;/strong&gt; (needs a real database and Hibernate 3.1 against a modern driver; that is where &quot;as few changes as possible&quot; stops being small).&lt;/p&gt;
&lt;h3&gt;Files&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt; (repo dir, two-stage: JDK 8 + Ant build, Tomcat 9 + JDK 8 runtime)&lt;/li&gt;&lt;li&gt;&lt;code&gt;deploy/entrypoint.sh&lt;/code&gt; (env var to properties file shim; seeds an empty volume)&lt;/li&gt;&lt;li&gt;&lt;code&gt;deploy/seed-blog/general/hello-world.html&lt;/code&gt; (one entry so the first page is not blank)&lt;/li&gt;&lt;li&gt;&lt;code&gt;deploy/README.md&lt;/code&gt; (this file)&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Nothing else in the tree was modified.&lt;/p&gt;
&lt;p&gt;Run locally:&lt;/p&gt;
&lt;pre&gt;docker build -t blojsom228 .
docker run -p 8080:8080 -e BLOJSOM_ADMIN_PASSWORD=changeme blojsom228
# http://localhost:8080/blojsom/blog/   admin: ?flavor=admin&lt;/pre&gt;
&lt;p&gt;Deploy (Railway, account already linked):&lt;/p&gt;
&lt;pre&gt;railway up --detach&lt;/pre&gt;
&lt;p&gt;Env vars the image understands: &lt;code&gt;PORT&lt;/code&gt;, &lt;code&gt;BLOJSOM_BASE_URL&lt;/code&gt;, &lt;code&gt;BLOJSOM_BLOG_HOME&lt;/code&gt;, &lt;code&gt;BLOJSOM_ADMIN_PASSWORD&lt;/code&gt;.&lt;/p&gt;
</description>
            <guid>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Deploying-blojsom-2-28-2006-on-a-modern-host-2026.html</guid>
			<pubDate>Sat, 5 Sep 2026 00:59:52 +0000</pubDate>
            <category>/general/</category>
              	          <wfw:comment>https://blojsom.audiodude.xyz/blojsom/commentapi/default/general/?permalink=Deploying-blojsom-2-28-2006-on-a-modern-host-2026.html</wfw:comment>
              <wfw:commentRss>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Deploying-blojsom-2-28-2006-on-a-modern-host-2026.html&amp;page=comments&amp;flavor=rss2</wfw:commentRss>
                                </item>
                <item>
            <title>Posted from the 2026 admin UI</title>
            <link>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Posted-from-the-2026-admin-UI.html</link>
            <description>&lt;p&gt;Written through blojsom 2.28&#39;s own admin console, running on Railway. If you can read this after a redeploy, the volume works.&lt;/p&gt;
</description>
            <guid>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Posted-from-the-2026-admin-UI.html</guid>
			<pubDate>Fri, 4 Sep 2026 23:57:53 +0000</pubDate>
            <category>/general/</category>
              	          <wfw:comment>https://blojsom.audiodude.xyz/blojsom/commentapi/default/general/?permalink=Posted-from-the-2026-admin-UI.html</wfw:comment>
              <wfw:commentRss>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=Posted-from-the-2026-admin-UI.html&amp;page=comments&amp;flavor=rss2</wfw:commentRss>
                                </item>
                <item>
            <title>Hello from 2006</title>
            <link>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=hello-world.html</link>
            <description>&lt;p&gt;This is blojsom 2.28, built from the SourceForge SVN tree with its original Ant build and running on Tomcat 9 / JDK 8 in a container. Entries are plain files in &lt;code&gt;blog-home&lt;/code&gt;; this one is &lt;code&gt;general/hello-world.html&lt;/code&gt;.&lt;/p&gt;
</description>
            <guid>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=hello-world.html</guid>
			<pubDate>Fri, 4 Sep 2026 23:51:56 +0000</pubDate>
            <category>/general/</category>
              	          <wfw:comment>https://blojsom.audiodude.xyz/blojsom/commentapi/default/general/?permalink=hello-world.html</wfw:comment>
              <wfw:commentRss>https://blojsom.audiodude.xyz/blojsom/blog/default/general/?permalink=hello-world.html&amp;page=comments&amp;flavor=rss2</wfw:commentRss>
                                </item>
            </channel>
</rss>
