Skip to content

Search these docs from your AI tool

  • Antigravity
    {
      "mcpServers": {
        "edisyl-docs": {
          "serverUrl": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • Claude CodeCLI
    claude mcp add edisyl-docs https://docs.edisyl.com/mcp --transport http --scope user
  • CodexCLI
    codex mcp add --url https://docs.edisyl.com/mcp edisyl-docs
  • Cursor
    {
      "mcpServers": {
        "edisyl-docs": {
          "type": "http",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • Gemini CLI
    gemini mcp add --transport http edisyl-docs https://docs.edisyl.com/mcp
  • Goose
    {
      "extensions": {
        "edisyl-docs": {
          "enabled": true,
          "name": "edisyl-docs",
          "type": "streamable_http",
          "uri": "https://docs.edisyl.com/mcp",
          "envs": {},
          "env_keys": [],
          "headers": {},
          "description": "",
          "timeout": 300,
          "bundled": null,
          "available_tools": []
        }
      }
    }
  • JetBrains AI Assistant
    {
      "mcpServers": {
        "edisyl-docs": {
          "type": "http",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }

    Paste into Settings → Tools → AI Assistant → Model Context Protocol → Add → As JSON. Direct file writing isn’t supported — JetBrains stores this per-version as XML.

  • Junie (JetBrains)
    {
      "mcpServers": {
        "edisyl-docs": {
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • OpenCode
    {
      "mcp": {
        "edisyl-docs": {
          "type": "remote",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • VS CodeCLI
    code --add-mcp '{"name":"edisyl-docs","type":"http","url":"https://docs.edisyl.com/mcp"}'
  • Windsurf
    {
      "mcpServers": {
        "edisyl-docs": {
          "serverUrl": "https://docs.edisyl.com/mcp"
        }
      }
    }

    Supports both stdio and native HTTP connections.

Registry access

Both the chart and the application images live in a private ECR registry. Access is read-only, scoped to your organisation’s repositories, and granted through an IAM role in Edisyl’s account that a principal in yours is allowed to assume. Nothing is shared: no registry password, no long-lived key.

Four steps, alternating sides. The first two happen before you touch a cluster; the last two are what the rest of this page walks through.

  1. You send Edisyl your AWS account ID and the ARN of the IAM principal that will assume the role — normally your cluster’s node role or an IRSA role; an IAM user also works. It must be a plain IAM role or user, not an SSO assumed-role ARN: our trust policy pins the principal’s unique ID, and SSO roles are recreated whenever their permission set changes.
  2. Edisyl creates your role and sends back the table below. The <name> in the role ARN is your client ID. Edisyl assigns it; you do not choose it. The same ID is the prefix your usage archives land under, which is why the configurator asks for it first and derives the role ARN from it everywhere.
  3. You allow the assume on your side — the policy in the next section. Our trust policy names your principal; your principal still has to be permitted to call sts:AssumeRole on our role.
  4. You configure the pull: a profile for helm pull, and the chart’s token refresher for the cluster, both further down.
What Edisyl sends you
Client ID The <name> in the role ARN below; also your usage-export prefix
Role ARN arn:aws:iam::944311261080:role/edisyl-client-<name>
External ID Not a secret, but required on every assume
Registry 944311261080.dkr.ecr.us-east-1.amazonaws.com
Region us-east-1
Repositories The chart and the images your role can read

If you have not received these, ask before going further — nothing below works without them.

Our trust policy naming your principal is only half of a cross-account assume. Attach this to the principal that will pull — normally your cluster’s node role or an IRSA role:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeEdisylRegistryRole",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::944311261080:role/edisyl-client-<name>"
}
]
}

Without it you get AccessDenied on sts:AssumeRole regardless of what we allow on our side.

~/.aws/config
[profile edisyl-registry]
role_arn = arn:aws:iam::944311261080:role/edisyl-client-<name>
external_id = <external-id>
region = us-east-1
# Where the credentials to assume FROM come from. Pick one:
source_profile = <your-profile> # an IAM user's keys
# credential_source = Ec2InstanceMetadata # an EC2 instance role
# credential_source = EcsContainer # an ECS task role

role_arn alone is not enough — without source_profile or credential_source the SDK has nothing to assume from.

If your principal is itself a role, this is role chaining and STS caps the session at one hour. Requesting longer fails.

Terminal window
aws ecr get-login-password --region us-east-1 --profile edisyl-registry \
| helm registry login --username AWS --password-stdin \
944311261080.dkr.ecr.us-east-1.amazonaws.com
helm pull oci://944311261080.dkr.ecr.us-east-1.amazonaws.com/edisyl-charts/edisyl-helm \
--version <chart-version>

Pick a version from the image matrix. Helm never needs to understand STS — it just receives the password.

ECR authorization tokens expire after 12 hours. An imagePullSecret holding one stops working overnight, and the failure is delayed rather than immediate: running pods keep running, and the first sign is an ImagePullBackOff on the next restart, rollout or scale-up — hours after the cause.

Pick one of the two approaches below. The chart ships the first.

images:
registry: 944311261080.dkr.ecr.us-east-1.amazonaws.com
pullSecret: edisyl-ecr
ecrRefresh:
enabled: true
region: us-east-1
# Cross-account, which is how Edisyl grants access. Omit both for a
# registry in your own account.
roleArn: arn:aws:iam::944311261080:role/edisyl-client-<name>
externalId: <external-id>

The chart then mints a fresh token and rewrites the secret every four hours. Four, not six: with a six-hour schedule a run at midnight, a missed one at 06:00 and the next at noon would land the refresh exactly on the expiry. At four, the same missed run still leaves four hours of margin.

The refresher can read and write only the one secret it maintains — get, patch and update on that name, with no create verb at all. That matters, because the same namespace holds your database credentials, the JWT signing keys and every third-party API key.

Its container image defaults to a public one, deliberately: an image pulled from our registry would mean an expired secret leaves you unable to run the one thing that fixes it.

The refresher refreshes and never creates. The initial pull secret is a prerequisite of installing at all, because the pre-install migrate hook pulls a first-party image before anything the chart renders could refresh it. If the secret is missing, the refresher says so rather than failing opaquely.

The chart can create it for you, which is the easier path. Two of the three values are not secret and belong in the file you commit:

edisyl.values.yaml
images:
pullSecret: edisyl-ecr # the NAME of the secret to create
pullSecretAuth:
enabled: true
username: AWS # always AWS for ECR

The password is an ECR authorization token, not your role ARN and not a long-lived key. You mint one with the profile configured above — which is where the role and external ID live — and hand it to helm on the command line:

Terminal window
helm install edisyl <chart> -n edisyl \
-f edisyl.values.yaml -f secrets.local.yaml \
--set-string images.pullSecretAuth.password="$(aws ecr get-login-password \
--region us-east-1 --profile edisyl-registry)"

Mint it at install time rather than saving it. The token lasts 12 hours, so one written into a file yesterday is already dead — and it is several kilobytes of base64, which is miserable to paste into YAML without mangling. Minting it inside the command keeps it off disk entirely and guarantees it is fresh.

Leave the flag off and the render stops with images.pullSecretAuth.password must be set, so this is not something you can forget silently.

The chart assembles the .dockerconfigjson itself from those three values — computing the auth field as base64 of AWS:<token> — so you are never asked to build that document by hand.

With ecrRefresh on, that seed is applied on install only, never on upgrade — otherwise the two would fight, and every helm upgrade would paste a token that died within twelve hours over whatever the refresher last wrote.

Three consequences worth knowing:

  • Seeding an ECR credential this way with ecrRefresh off is refused at render. On its own it is a cluster that pulls today and cannot pull tomorrow.
  • helm uninstall leaves this secret behind, because Helm does not track hook resources. Delete it by hand.
  • Under Argo CD, leave pullSecretAuth off and seed out of band: PreSync runs on every sync rather than once.

Or create it by hand. The profile you configured above already carries the role and the external ID, so this needs no separate assume-role step:

Terminal window
kubectl -n edisyl create secret docker-registry edisyl-ecr \
--docker-server=944311261080.dkr.ecr.us-east-1.amazonaws.com \
--docker-username=AWS \
--docker-password="$(aws ecr get-login-password \
--region us-east-1 --profile edisyl-registry)" \
--dry-run=client -o yaml | kubectl apply -f -

Three things about that command.

It is written to be re-run. kubectl create secret on its own fails with AlreadyExists the second time, which is exactly when you need it — the token lasts 12 hours, and a rebuild or an expired credential both send you back here. Rendering the manifest and piping it to apply replaces the secret in place instead.

The server is the registry HOST, with no path. images.registry carries /edisyl-prd because it composes image references; a docker credential is scoped to the host alone, and one written against the path-suffixed string is simply never matched to the pull.

kubectl create secret docker-registry has no --docker-password-stdin, so the token goes on the command line and your shell history will hold it. Clear it afterwards if that matters to you.

Check what you actually created before installing — the secret is a .dockerconfigjson document, and a wrong host or a truncated password is invisible until a pod fails to pull:

Terminal window
kubectl -n edisyl get secret edisyl-ecr \
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | python3 -m json.tool

You want one entry under auths, keyed by the registry host above, with username: AWS and a non-empty password.

An imagePullSecret is namespace-local, so it has to live in the namespace you install into — creating it in default and installing into edisyl leaves the pull unauthenticated with nothing saying why.

The pod’s own identity is what assumes the role above. It comes from IRSA — name the role in ecrRefresh.serviceAccountAnnotations — or from EKS Pod Identity, whose association is created outside Helm:

Terminal window
aws eks create-pod-identity-association \
--cluster-name "$CLUSTER" --namespace edisyl \
--service-account ecr-refresh --role-arn "$YOUR_ROLE_ARN" \
--disable-session-tags

--disable-session-tags is not optional for a cross-account pull. Pod Identity attaches transitive session tags by default, and a transitive tag carried into the second AssumeRole requires the destination trust policy to allow sts:TagSession. Our client role allows sts:AssumeRole only, so leaving tags on fails the second hop with an AccessDenied that names neither tags nor the reason.

Cleanest where your distribution supports it. Configure ecr-credential-provider on each node with the profile above. There is no secret to rotate and nothing to refresh — leave both images.pullSecret and ecrRefresh unset.

Requires Docker. If you have not got it, the helm pull above is already evidence that the role and the chart repository work.

Terminal window
aws ecr get-login-password --region us-east-1 --profile edisyl-registry \
| docker login --username AWS --password-stdin \
944311261080.dkr.ecr.us-east-1.amazonaws.com
docker pull 944311261080.dkr.ecr.us-east-1.amazonaws.com/edisyl-prd/mono-api:<tag>

Then confirm the boundary holds. Pick any repository not on the list we gave you — this must fail with AccessDenied:

Terminal window
docker pull 944311261080.dkr.ecr.us-east-1.amazonaws.com/edisyl-prd/<not-granted>:<tag>

If it succeeds, tell us immediately — it means your role is not scoped correctly.

Tell us and we delete the role. New assumes fail at once; a token already issued keeps working until it expires, up to 12 hours later.

Report incorrect code

Please provide a detailed description of the incorrect code.