Your first server is on us — no card, no catch

Minecraft hosting,
built different.

Start with a free 2GB server — live in under 60 seconds, no card needed. Every server includes TCPShield DDoS protection. Upgrade to premium plans from £9.99/mo when you're ready.

No credit card
Cancel anytime
60-second setup
DDoS protected
Free 2GB Starter
Perfect for getting started
£0/mo
No time limit
2GB
RAM
<60s
Setup
2–10
Players
Pterodactyl panel access
TCPShield DDoS protection
Vanilla, Paper, Fabric support
Add users via Minecraft UUID
1 free server per account · No time limit · UK hosted
6
Plan tiers
<60s
Setup time
£0
To start
TCPShield
DDoS layer
TCPShield DDoS protection on every server
No credit card · No time limit on free tier
Live in under 60 seconds
UK hosted · Hetzner London
Platform

Minecraft server hosting built different.

Every feature shipped because a player asked for it. Real priorities, not marketing fluff. UK hosted on Hetzner — fast for your players.

Instant setup

Live in under 60 seconds. Choose your version, pick your software, and your server is running — no waiting, no tickets.

TCPShield DDoS protection

Every server sits behind TCPShield. Attackers hit our proxy, not your server. Your players stay connected no matter what.

UUID-based permissions

Give co-owners and admins panel access using their Minecraft username or UUID. Simple, secure, no shared passwords.

Built by a player

LowLight is run by someone in the Minecraft community. We host PVP texture packs in the Discord. We get it.

Pterodactyl panel

The industry standard. Manage your server, upload files, view console output, schedule restarts — all in one place.

Automated backups

Daily automated backups on all paid plans. One-click restore if anything goes wrong. Your world is safe with us.

Pricing

Simple, honest pricing

No hidden fees. No auto-upgrades. Pay for what you use.

Free 2GB
Free
2 GB RAM · 2–10 players
£0 / forever
  • Vanilla, Paper, Fabric
  • TCPShield DDoS protection
  • Pterodactyl panel
  • Add 3 users via UUID
  • Community Discord
  • No automated backups
1 free server per account
Essential
Starter
4 GB RAM · up to 20 players
£ 9.99 /mo
  • Everything in Free
  • 1 daily backup · 3 days
  • Add 10 users via UUID
  • Priority support
Advanced
Pro
16 GB RAM · up to 120 players
£ 34.99 /mo
  • Everything in Standard
  • 3 daily backups · 14 days
  • Full modpack support
  • Custom subdomain
Pro
Pro
24 GB RAM · up to 200 players
£ 49.99 /mo
  • Everything in Advanced
  • 6 daily backups · 30 days
  • Dedicated Discord support
Ultimate
Power
32 GB RAM · large networks
£ 69.99 /mo
  • Everything in Pro
  • Multiple server support
  • SLA uptime guarantee
Titan
Power
48–64 GB RAM · networks
£ 99.99 /mo
  • Everything in Ultimate
  • Network-grade infrastructure
  • Dedicated account manager
Custom
Bespoke
128GB · 256GB · tailored
Tailored
  • Everything in Titan+
  • Custom infrastructure
  • Volume pricing
  • White-glove onboarding
Contact us on Discord
Cancel any time
Proration on upgrades
No long-term contracts
Billed monthly · Switch plans any time · Proration handled automatically
Plan calculator

Find your perfect plan

Tell us your server type and player count. We'll recommend the right tier.

Join the community
Find servers, get support, connect with other players on our Discord.
Join Discord Browse servers
FAQ

Common questions

We use cookies to keep you logged in. We never sell your data. Privacy policy · UK GDPR compliant · Must be 16+

════════════════════════════════════════════════════════════════ */ // ── YOUR KEYS (replace these) ── var SUPABASE_URL = 'https://tqbenxlybepxuhcmkduh.supabase.co'; // e.g. https://abcdefgh.supabase.co var SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRxYmVueGx5YmVweHVoY21rZHVoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzgwMDY3MzksImV4cCI6MjA5MzU4MjczOX0.cuYR-KWQZXfjvkzwD2LjnzQdwt2YFQkxqWMpXfT4hpI'; // The anon public key (starts with eyJ...) // ── INIT ── var llSupabase; try { llSupabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY); } catch(e) { console.error('LowLight: Failed to init Supabase client', e); } // ════════════════════════════════════════════════════════════════ // AUTH FUNCTIONS — called by your HTML onclick handlers // ════════════════════════════════════════════════════════════════ /** * Sign up a new user. * Call this from your signup form's submit button. * * @param {string} email * @param {string} password * @param {string} username * @returns {object} { success, error, user } */ async function llSignup(email, password, username) { try { const { data, error } = await llSupabase.auth.signUp({ email: email, password: password, options: { data: { username: username } // Stored in user metadata, used by the trigger to create profile } }); if (error) return { success: false, error: error.message }; // Update nav llUpdateNavFromSession(); return { success: true, user: data.user }; } catch (err) { return { success: false, error: 'Something went wrong. Please try again.' }; } } /** * Log in an existing user. * * @param {string} email * @param {string} password * @returns {object} { success, error, user } */ async function llLogin(email, password) { try { const { data, error } = await llSupabase.auth.signInWithPassword({ email: email, password: password }); if (error) return { success: false, error: error.message }; // Update nav llUpdateNavFromSession(); return { success: true, user: data.user }; } catch (err) { return { success: false, error: 'Something went wrong. Please try again.' }; } } /** * Log out the current user. */ async function llSignOut() { await llSupabase.auth.signOut(); llUpdateNavFromSession(); window.location.href = '/'; } /** * Get the current logged-in user (or null). */ async function llGetUser() { const { data: { user } } = await llSupabase.auth.getUser(); return user; } /** * Get the current user's profile from the profiles table. */ async function llGetProfile() { const user = await llGetUser(); if (!user) return null; const { data, error } = await supabase .from('profiles') .select('*') .eq('id', user.id) .single(); if (error) return null; return data; } // ════════════════════════════════════════════════════════════════ // NAV STATE — shows/hides login buttons and avatar // ════════════════════════════════════════════════════════════════ async function llUpdateNavFromSession() { const user = await llGetUser(); var loginBtn = document.getElementById('navLoginBtn'); var signupBtn = document.getElementById('navSignupBtn'); var serversBtn = document.getElementById('navServersBtn'); var avatarBtn = document.getElementById('navUserAvatar'); if (user) { // Logged in if (loginBtn) loginBtn.style.display = 'none'; if (signupBtn) signupBtn.style.display = 'none'; if (serversBtn) serversBtn.style.display = 'inline-flex'; if (avatarBtn) avatarBtn.style.display = 'flex'; } else { // Logged out if (loginBtn) loginBtn.style.display = ''; if (signupBtn) signupBtn.style.display = ''; if (serversBtn) serversBtn.style.display = 'none'; if (avatarBtn) avatarBtn.style.display = 'none'; } } // ════════════════════════════════════════════════════════════════ // AUTH STATE LISTENER — auto-updates when login state changes // ════════════════════════════════════════════════════════════════ llSupabase.auth.onAuthStateChange(function(event, session) { llUpdateNavFromSession(); }); // ════════════════════════════════════════════════════════════════ // FORM HANDLERS — connect to your overlay forms // These replace the demo llDoLogin/llLogin functions. // ════════════════════════════════════════════════════════════════ /** * Handle the login form submission. * Reads values from the login overlay inputs and calls Supabase. */ async function handleLoginSubmit() { var emailInput = document.getElementById('llLUser') || document.getElementById('loginUser'); var passInput = document.getElementById('llLoginPass') || document.getElementById('loginPass'); var submitBtn = document.querySelector('#llLoginOv .ov-go') || document.querySelector('#loginOverlay .btn-primary'); var errorEl = document.getElementById('loginError'); if (!emailInput || !passInput) return; var email = emailInput.value.trim(); var password = passInput.value; if (!email || !password) { if (errorEl) errorEl.textContent = 'Please enter your email and password.'; return; } // Show loading state if (submitBtn) { submitBtn.textContent = 'Logging in...'; submitBtn.disabled = true; } var result = await llLogin(email, password); if (result.success) { // Close the overlay if (typeof llClose === 'function') llClose('login'); if (typeof closeOverlay === 'function') closeOverlay('login'); // Redirect to servers page window.location.href = '/servers'; } else { // Show error if (errorEl) { errorEl.textContent = result.error; errorEl.style.display = 'block'; } else { alert(result.error); } if (submitBtn) { submitBtn.textContent = 'Log in'; submitBtn.disabled = false; } } } /** * Handle the signup form submission. */ async function handleSignupSubmit() { var userInput = document.getElementById('llSUser') || document.getElementById('signupUser'); var emailInput = document.getElementById('llSignupEmail') || document.getElementById('signupEmail'); var passInput = document.getElementById('llSignupPass') || document.getElementById('signupPass'); var submitBtn = document.querySelector('#llSignupOv .ov-go') || document.querySelector('#signupOverlay .btn-primary'); var errorEl = document.getElementById('signupError'); var username = userInput ? userInput.value.trim() : ''; var email = emailInput ? emailInput.value.trim() : ''; var password = passInput ? passInput.value : ''; // Validate if (!username || username.length < 3) { showFormError(errorEl, 'Username must be at least 3 characters.'); return; } if (!email || !email.includes('@')) { showFormError(errorEl, 'Please enter a valid email address.'); return; } if (!password || password.length < 8) { showFormError(errorEl, 'Password must be at least 8 characters.'); return; } // Show loading state if (submitBtn) { submitBtn.textContent = 'Creating account...'; submitBtn.disabled = true; } var result = await llSignup(email, password, username); if (result.success) { // Close overlay if (typeof llClose === 'function') llClose('signup'); if (typeof closeOverlay === 'function') closeOverlay('signup'); // Show success message or redirect alert('Account created! Check your email to verify, then log in.'); // Open login overlay if (typeof llOpen === 'function') llOpen('login'); if (typeof openOverlay === 'function') openOverlay('login'); } else { showFormError(errorEl, result.error); if (submitBtn) { submitBtn.textContent = 'Create account'; submitBtn.disabled = false; } } } function showFormError(el, msg) { if (el) { el.textContent = msg; el.style.display = 'block'; } else { alert(msg); } } // ════════════════════════════════════════════════════════════════ // DATA HELPERS — use these to read/write to your tables // ════════════════════════════════════════════════════════════════ /** * Get all servers belonging to the current user. */ async function llGetServers() { const { data, error } = await supabase .from('servers') .select('*') .order('created_at', { ascending: false }); if (error) { console.error('Error fetching servers:', error); return []; } return data; } /** * Get a single server by ID. */ async function llGetServer(serverId) { const { data, error } = await supabase .from('servers') .select('*') .eq('id', serverId) .single(); if (error) return null; return data; } /** * Create a new server. */ async function llCreateServer(serverData) { const user = await llGetUser(); if (!user) return { success: false, error: 'Not logged in' }; const { data, error } = await supabase .from('servers') .insert({ user_id: user.id, name: serverData.name || 'My Server', subdomain: serverData.subdomain, version: serverData.version || '1.21.4', server_type: serverData.serverType || 'vanilla', ram_mb: serverData.ramMb || 2048, max_players: serverData.maxPlayers || 20, plan: 'free' }) .select() .single(); if (error) return { success: false, error: error.message }; return { success: true, server: data }; } /** * Update server settings. */ async function llUpdateServer(serverId, updates) { const { data, error } = await supabase .from('servers') .update(updates) .eq('id', serverId) .select() .single(); if (error) return { success: false, error: error.message }; return { success: true, server: data }; } /** * Delete a server. */ async function llDeleteServer(serverId) { const { error } = await supabase .from('servers') .delete() .eq('id', serverId); if (error) return { success: false, error: error.message }; return { success: true }; } /** * Get the current user's referral stats. */ async function llGetReferralStats() { const user = await llGetUser(); if (!user) return null; const profile = await llGetProfile(); const { data: referrals } = await supabase .from('referrals') .select('*') .eq('referrer_id', user.id); return { code: profile ? profile.referral_code : null, credit: profile ? profile.referral_credit : 0, totalReferrals: referrals ? referrals.length : 0, confirmedReferrals: referrals ? referrals.filter(function(r) { return r.status === 'confirmed'; }).length : 0, pendingReferrals: referrals ? referrals.filter(function(r) { return r.status === 'pending'; }).length : 0 }; } // ════════════════════════════════════════════════════════════════ // INIT ON PAGE LOAD // ════════════════════════════════════════════════════════════════ (async function() { // Update nav immediately based on current session await llUpdateNavFromSession(); })();