Skip to content
Scalpels home

Scalpels is officially launching on October 31, 2026. Sign up now for $10 in credit on a new Laravel Cloud account.

← All ideas and experiments

Experiment

We Installed Apache Answer on Laravel Cloud

· Claude Code

The idea asked whether the official Apache Answer release could become a Scalpels marketplace package without turning into a maintained fork.

Answer 2.0.3 ran on Laravel Cloud's native Go runtime with one ARM64 application replica, managed MySQL 8.4, managed Valkey, and a public object-storage bucket. There was no Dockerfile, PHP application, or Laravel wrapper. We exercised the core Q&A flow and found no hard platform blocker, but two official plugins needed patches and the install still needs production packaging.

What we assumed

We guessed What happened
The official ARM64 binary could run on Cloud's Go runtime Right. Answer listened on the assigned port over IPv6 and ran behind Cloud's proxy.
The plugin build would need Go, Node, and pnpm Right. Answer's official builder rebuilt the server and React interface with the S3 and Redis plugins.
First boot needed a launcher and a private deploy-time bootstrap Right. The launcher generated configuration, initialized MySQL, and ran upgrades before the web process took traffic.
MySQL plus object storage would carry durable state Mostly right. Q&A data, accounts, settings, and uploads survived deployments, but we did not predict that login sessions lived in the local cache file.
The S3 plugin would mishandle attachment MIME types Right. A text file came back as image/txt until we patched the plugin.
SMTP needed administration setup and delivery evidence Right. The provider logged the handoff. We have not confirmed that mail reached an inbox or that an emailed link works.

Building and starting Answer

The build downloaded the official Answer 2.0.3 Linux release, verified its SHA-256, and pinned the official plugin repository to a specific commit. Answer's plugin builder then compiled in the S3 and Redis plugins. It needed Go, Node, and pnpm, and it rebuilt the React interface. The first Cloud build command took 80 seconds.

A small Go launcher handled the Cloud-specific work. On every boot it parsed the injected MySQL URL, wrote data/conf/config.yaml, recreated local directories, and ran answer init to restore translations or bootstrap a new database. The deploy command also ran answer upgrade. Normal startup replaced the launcher process with Answer so termination signals reached the server.

We ran the bootstrap with one replica on a separate, non-public installer port. We created the administrator during the deploy command, before we sent any traffic to the application. That avoided the first-visitor takeover window we were looking for. It did not prove that concurrent bootstrap is safe. Answer's initialization checks are not a cross-process lock, and a failure after the version table is created can leave a partial install that later runs may treat as complete.

Object storage exposed two traps

Answer's S3 plugin is configured through its administration API, and its settings persist in MySQL. Our first upload failed even though the plugin accepted the configuration. Cloud injects the bucket's physical identifier as the bucket name. The display name is not accepted by the storage service. We replaced the display name with the injected value, and the upload worked.

We then uploaded and downloaded images, and they remained intact. When we tested attachments, we hit the plugin bug we predicted. Answer starts with no permitted attachment extensions, and the setting takes bare values such as txt rather than .txt. Once we enabled them, we uploaded a text attachment and it came back as image/txt because the plugin built every content type as image/<extension>.

The patch replaces that guess with Go's MIME lookup and falls back to application/octet-stream when no type is known. After we rebuilt it, text and PDF downloads returned text/plain; charset=utf-8 and application/pdf, and both files matched what we uploaded. This is an upstream plugin bug we could contribute back. We have not done so.

The bucket we tested was public. The plugin joins a public visit URL to each object key and does not generate signed URLs, so private-bucket delivery still needs a different answer.

The surprise was session storage

After our first full deployment, the question, answer, accepted-answer state, vote, comment, accounts, settings, and object-storage image were all still there. But we were logged out of every browser.

Answer's default cache is held in memory and periodically saved to a local file. Login sessions and reset links use that cache. We missed that during the pre-build research. Cloud replaces the local filesystem during a deployment, so sessions disappeared with it.

The official Redis cache plugin could move that state to managed Valkey, but it accepted only a bare address and did not enable TLS. Cloud's Valkey connection uses rediss://. We patched the plugin to parse Redis URLs with the Redis driver's own parser while retaining separate username and password fields and certificate verification. This is the second upstream bug we could contribute back. Again, we have not claimed or submitted a contribution.

We hit one more configuration failure before it worked. We used the hostname the cache resource API gave us, which was the public one for a private cache, and connections reset. The injected Redis URL contained the working private hostname. We recovered without a login using Answer's supported deactivate_plugin command, changed the endpoint, and enabled the plugin again.

Answer chooses its cache backend at process start. Enabling Redis does not migrate sessions that already exist in memory, so we restarted it once more before we logged in and created the session we would test across the final deployment. After we built and rolled out again, the administrator token from that session still worked for both user information and the protected dashboard.

What worked live

We registered a separate member and activated it with an administrator-generated link. We created a question in the browser with a tag and an image, and the member answered it. The administrator upvoted the answer, accepted it, and added a comment. Reputation and badges updated. SQL-backed search found the question, and both plugin configurations remained available.

After the final deployment, the same authenticated administrator session worked without another login. The question, answer, vote, accepted state, comment, accounts, and settings were still present. Search worked, both plugins were enabled, and the original PNG, text attachment, and PDF still downloaded unchanged.

SMTP logs showed successful handoff for a test email, registration message, and password-reset message. We did not verify inbox receipt or complete a link received by email. We activated the account with the administrator-generated link instead.

What we did not exercise

We used one always-on application replica. We did not test multiple replicas, autoscaling, hibernation, disaster recovery, or load. We also did not exercise OAuth and other external identity providers, AI provider plugins, optional search engines, or CDN behaviour. MySQL connected without a TLS option in the generated connection string, but we did not investigate its TLS policy.

Where this leaves the marketplace question

There is no hard blocker in the workflows we tested, and the marketplace decision is still open. A repeatable package would need to automate post-install plugin and SMTP configuration, remove first-install administrator secrets after bootstrap, define backups and upgrades, and account for a one-replica first installation. The Redis TLS and S3 MIME fixes should also be proposed upstream or carried deliberately before Answer could be listed.

The idea behind this experiment

  1. Idea

    Could Apache Answer run on Laravel Cloud?

    We want to know whether Apache Answer belongs in the Scalpels marketplace. Its official release is a Go program, not a Laravel application. Some of what it needs to keep running, like its configuration and uploads, lives outside that program. Before deploying it, we wrote down where we expected trouble.

    Read the idea

Support the Lab

The Lab runs on our supporters

Every idea here gets tried for real: deployed, broken, fixed and written up. Right now that is one person doing the work between everything else, and supporters are what buy the time. As support grows, it will also pay freelancers to run experiments of their own, so more of these ideas get tested, sooner.

Our supporters

  • Sputnik Intelligence

    Spain

    We transcribe the podcasts and read the newsletters, and make them searchable. Set up alerts, or hand it all to your AI agent over MCP or API.

    Supporter Visit
    Visit Sputnik Intelligence