+
-
-
+
+
Templates
@@ -231,15 +231,15 @@
-
-
Name
- Type
- vCPUs
- Memory
- Size
- Created
- Actions
+
+
+
{#each Array(4) as _, i}
Name
+ Type
+ vCPUs
+ Memory
+ Size
+ Created
+ Actions
-
-
-
-
+
+
@@ -329,16 +327,16 @@
{:else}
-
+
-
-
+
{emptyHeading(typeFilter)}
-+
{emptyDescription(typeFilter)}
{#if typeFilter === 'all' || typeFilter === 'snapshot'} Go to Capsules
+
{/if}
@@ -715,17 +717,17 @@
.skeleton {
background: linear-gradient(
90deg,
- var(--color-bg-4) 0%,
- var(--color-bg-5) 50%,
- var(--color-bg-4) 100%
+ var(--color-bg-3) 25%,
+ var(--color-bg-4) 50%,
+ var(--color-bg-3) 75%
);
background-size: 200% 100%;
- animation: shimmer 1.6s ease-in-out infinite;
+ animation: shimmer 1.4s ease infinite;
}
@keyframes shimmer {
- 0% { background-position: 200% center; }
- 100% { background-position: -200% center; }
+ 0% { background-position: -200% 0; }
+ 100% { background-position: 200% 0; }
}
/* Left accent stripe — slides in on hover, color-keyed to snapshot type */
@@ -745,4 +747,9 @@
.snapshot-row.type-image:hover {
background: rgba(90, 159, 212, 0.04);
}
+
+ /* Empty state icon float — matches admin pattern */
+ .empty-icon-float {
+ animation: iconFloat 3s ease-in-out infinite;
+ }
diff --git a/images/wrenn-init.sh b/images/wrenn-init.sh
index d83be1c..8a9e22e 100644
--- a/images/wrenn-init.sh
+++ b/images/wrenn-init.sh
@@ -17,8 +17,9 @@ mkdir -p /sys/fs/cgroup
mount -t cgroup2 cgroup2 /sys/fs/cgroup 2>/dev/null || true
echo "+cpu +memory +io" > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true
-# Set hostname
+# Set hostname and make it resolvable (sudo requires this).
hostname sandbox
+echo "127.0.0.1 sandbox" >> /etc/hosts
# Configure networking if the kernel ip= boot arg did not already set it up.
if ! ip addr show eth0 2>/dev/null | grep -q "169.254.0.21"; then
diff --git a/internal/service/build.go b/internal/service/build.go
index 55defe6..c0aa8c6 100644
--- a/internal/service/build.go
+++ b/internal/service/build.go
@@ -420,8 +420,10 @@ func (s *BuildService) executeBuild(ctx context.Context, buildIDStr string) {
}
// Capture the final user and env vars as template defaults.
+ // Filter out user-specific and runtime vars that should be resolved at
+ // sandbox creation time, not baked in from the build environment.
templateDefaultUser := bctx.User
- templateDefaultEnv := bctx.EnvVars
+ templateDefaultEnv := filterBuildEnv(bctx.EnvVars)
// Phase 3: Post-build (as root) — cleanup.
bctx.User = "root"
@@ -739,3 +741,27 @@ func (s *BuildService) uploadAndExtractArchive(
return nil
}
+
+// runtimeEnvVars lists env vars that are user- or session-specific and should
+// not be persisted into template defaults. These are resolved at runtime by
+// envd based on the actual user and sandbox context.
+var runtimeEnvVars = map[string]bool{
+ "HOME": true, "USER": true, "LOGNAME": true, "SHELL": true,
+ "PWD": true, "OLDPWD": true, "HOSTNAME": true, "TERM": true,
+ "SHLVL": true, "_": true,
+ // Per-sandbox identifiers set by envd at boot via MMDS.
+ "WRENN_SANDBOX_ID": true, "WRENN_TEMPLATE_ID": true,
+}
+
+// filterBuildEnv returns a copy of envVars with runtime/user-specific
+// variables removed so they don't override envd's per-user resolution.
+func filterBuildEnv(envVars map[string]string) map[string]string {
+ filtered := make(map[string]string, len(envVars))
+ for k, v := range envVars {
+ if runtimeEnvVars[k] {
+ continue
+ }
+ filtered[k] = v
+ }
+ return filtered
+}
-
-
{/if}
@@ -591,11 +591,15 @@
>Name
- Type
- vCPUs
- Memory
- Size
- Created
- Actions
+
+
@@ -366,17 +364,14 @@
Name
+ Type
+ vCPUs
+ Memory
+ Size
+ Created
+ Actions
{#if isSnapshot}
-
-
- Snapshot
+
+
+ snapshot
{:else}
-
-
- Image
+
+
+ image
{/if}
@@ -475,7 +470,7 @@
-
-
Launch Capsule
-+ +
+ +
+
Launch Capsule
+Configure resources and launch a new capsule from this snapshot.
@@ -612,12 +616,9 @@
{#if launchTarget.type === 'snapshot'}
-
+
{:else}
-
+
{/if}
{launchTarget.name}
@@ -694,7 +695,7 @@
+