Generic Java Runtime

Run arbitrary Java apps on Witchly.host. Upload your JAR and run it with configurable flags — great for bots, Spring Boot apps, and custom server software.

Generic Java Runtime

The Generic Java egg runs any executable JAR with Java 8. It’s a minimal, flexible runtime — upload your .jar, set the filename, start the server. Great for Discord bots (JDA, Discord4J), Spring Boot microservices, and custom tooling.

Note: This egg is configured for Java 8. For newer Java versions (17, 21, etc.), most Minecraft-focused eggs have better defaults — or contact support to have a custom egg provisioned.

Quick deploy

  1. dash.witchly.hostDeployLanguagesGeneric Java.
  2. SFTP your .jar file to /home/container/.
  3. On the Startup tab, set JAR FILE to your JAR’s filename.
  4. Start.

Startup flow

java -Dterminal.jline=false -Dterminal.ansi=true -jar {{JARFILE}}

Everything after the -jar is fixed to your JAR file. Customize JVM flags by editing the startup command:

java -Xmx${SERVER_MEMORY}M -Xms512M \
  -Dterminal.jline=false -Dterminal.ansi=true \
  -jar {{JARFILE}}

Variables reference

VariablePurpose
JARFILEName of your JAR in /home/container/

That’s it — this is a minimal egg. Any other configuration happens in your JAR, via application.properties, env vars, or CLI args.

Memory tuning

Java doesn’t know about cgroup memory limits prior to Java 10. Always set -Xmx explicitly:

-Xmx${SERVER_MEMORY}M  → caps the JVM heap at your plan's RAM

On The Script (512 MB), try -Xmx400M — leaving ~100 MB for metaspace and native memory. On larger plans you can use more of the RAM.

Spring Boot example

Build your Spring Boot fat JAR locally:

./mvnw clean package
# produces target/myapp-0.0.1-SNAPSHOT.jar

SFTP the JAR to /home/container/, set JARFILE = myapp-0.0.1-SNAPSHOT.jar, and update the startup to bind the port:

java -Xmx${SERVER_MEMORY}M \
  -Dserver.port=${SERVER_PORT} \
  -jar {{JARFILE}}

Your app is reachable at your server’s IP:PORT.

JDA Discord bot example

// Bot.java
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.requests.GatewayIntent;

public class Bot {
    public static void main(String[] args) throws Exception {
        JDABuilder.createDefault(System.getenv("DISCORD_TOKEN"))
            .enableIntents(GatewayIntent.MESSAGE_CONTENT)
            .build();
    }
}

Build a fat JAR with the shade/assembly plugin, upload, set DISCORD_TOKEN via env, start.

Setting environment variables

Pterodactyl variables appear as process.env-equivalent in Java. Either read them directly with System.getenv("DISCORD_TOKEN") or pass them in the startup:

java -DdiscordToken=${DISCORD_TOKEN} -jar {{JARFILE}}

then in Java: System.getProperty("discordToken").

Troubleshooting

  • “Could not find or load main class” — your JAR isn’t executable. Check MANIFEST.MF has Main-Class:, or use a shaded/fat JAR builder.
  • OutOfMemoryError — raise -Xmx or upgrade your plan.
  • ClassNotFoundException — your dependencies aren’t bundled; build a shaded/fat JAR or upload dependencies to /home/container/libs/ and add them to the classpath.

Next steps

  • If you need Java 17+, ask us to provision a custom egg, or use one of the Minecraft eggs as a base
  • Pair with MariaDB or Postgres for persistence