How do I disable candid UI deployment when deploying to custom network

I’m working with multiple custom environments to deploy to specific canister on mainnet, but it appears that specifying a network other then --network ic trigger a deployment of a canister for the candid UI.

Is there any argument i can pass on / rule i can set to disable this behaviour?

it feels like there is some check going on like

if network != 'ic' {

When specifying an other environment i get the following error;

  Failed to install candid UI canister.
    Create canister call failed.
      The replica returned a replica error: reject code CanisterReject, reject message Caller <IDENTITY_PRINCIPAL> is not allowed to call ic00 method provisional_create_canister_with_cycles, error code Some("IC0516")


  "parent": {
    "ic": "aaaaa-aa",
    "staging": "bbbbb-bb",
    "development": "ccccc-ccc"


  "local": {
    "bind": "",
    "type": "ephemeral",
    "replica": {
      "subnet_type": "system"
  "ic": {
    "providers": [
    "type": "persistent"
  "staging": {
    "providers": [
    "type": "persistent"
  "development": {
    "providers": [
    "type": "persistent"

Just checked the code and I don’t see a way to disable it getting installed. But if dfx recognises that you’re running on mainnet it won’t install candid UI. If you change the provider to it will notice it’s mainnet. Is there a specific reason you’re using the URL in your dfx.json instead of the ‘default’ one?


Thanks for the help, I copy-pasted it from somewhere but i can’t recall where from, could be that it was set in my global networks.json.

1 Like

Hello, Dfinity Forum.

I have read this topic before issuing dfx deploy --ic and relied on the truthfulness of @Severin 's “But if dfx recognises that you’re running on mainnet it won’t install candid UI.

Unfortunately, the candid UI has been deployed. Which is a HUGE security risk for me.

So how do I disable candid UI when deploying to mainnet?

How do you define mainnet? Can you show this? I’d like to add this to the recognition logic

Workaround: define canister __Candid_UI as remote on the network that you don’t want it deployed on

Hi, Sevrin.

I do not define mainnet in any other way than the following does:

dfx deploy --network ic

The `--network` option specifies the network alias or URL for deploying the dapp. 
This option is required to install on the Internet Computer blockchain mainnet.

To be found under Mainnet deployment.

How do you define a workaround? Do you mean I should create a file named workaround.json in the project’s root and put { “__Candid_UI”: “remote” } into it?

Do you mean it has been deployed to a4gq6-oaaaa-aaaab-qaa4q-cai? That is not your deployment, it is one maintained by the Candid team

Thanks for your patience, Severin.

I was a bit frustrated by the lack of information about that __Candid_UI key - especially after finding internet-identity/demos/using-dev-build/dfx.json at main · dfinity/internet-identity · GitHub with the promising but dead link on top.

My point here is: I do not wish to expose my canister’s API through Candid UI - especially if it is not my deployment as you say. I do not wish for anybody to be able to see my canister’s method names AND SIGNATURES. And I simply fail to understand by what right your Candid team exposes my interfaces to the world. I also fail to see how your statement “But if dfx recognises that you’re running on mainnet it won’t install candid UI.” could be interpreted in any other way than I did: no candid UI on mainnet.

It all boils down to 2 questions:

  1. how can I undo the publishing of my API on a4gq6-oaaaa-aaaab-qaa4q-cai?
  2. how can I prevent such a publishing in the future?

Thanks in advance for your answers,


Ah, now we’re getting to the bottom of the issue. The problem is not Candid UI, but instead the publishing of your canister interface in the canister metadata. To explain a bit:

Most canisters publish their interface publicly in the candid:service metadata section. You can try it yourself using dfx canister metadata <canister name/id> candid:service. Candid UI reads this metadata to determine the interface of your canister (therefore it doesn’t publish any more info than is already public).

dfx makes the candid:service metadata section public by default for two reasons: First it’s very convenient to be able to use Candid UI and similar tools without any extra setup. Second, we decided we want to promote interoperability and having public interfaces by default helps a lot with that issue. As an additional side benefit it makes my (and other people’s) life easier when debugging problems. E.g. it is very easy to notice someone is targeting the wrong canister if the interface is that of the other canister in the project. Of course you’re welcome to disagree with this decision. If you feel very strongly about it, please start a discussion about it in another thread and tag me.

Now, to what you actually can do: If you make the candid:service metadata section private then it’s only readable by controllers of the canister (read: you and your wallet canister, otherwise nobody unless you add them explicitly). You can do it by adding this to your canister definition in dfx.json:

      "metadata": [
          "name": "candid:service",
          "visibility": "private"

When you add this and redeploy your canister then the interface is no longer published

Side note: I strongly disagree that this is a HUGE SECURITY ISSUE. If your app is secure then using some security by obscurity on top is a nice bonus, but it’s not something you should rely on. If you rely on that obscurity as a major measure of security I suggest you reconsider some parts. Therefore I also think your first post was a bit overly dramatic :slightly_smiling_face:

1 Like

Thanks very much for your reply, Severin.

Unfortunately, the candid interface still gets published (after dfx start --clean; create canisters anew).
Here is my dfx.json

  "canisters": {
    "bmos": {
      "type":           "motoko",
      "main":           "backend/",
      "declarations": {
        "output":         "declarations/bmos"
      "metadata": [{
        "name":           "candid:service",
        "visibility":     "private"
    "frontend": {
      "dependencies":   [ "bmos" ],
      "source":         [ "dist/" ],
      "type":           "assets"
  "defaults": {
    "build": {
      "args":           "",
      "packtool":       "mops sources"
  "output_env_file":  ".env",
  "version":          2

output of dfx deploy bmos (dfx 0.17.0):

  Backend canister via Candid interface:

P.S. I totally agree with your statements about obscurity vs. security. However, mislead by your statement “But if dfx recognises that you’re running on mainnet it won’t install candid UI.”, I deployed sensitive data for a test prior to implementing ‘proper’ security.

It looks like you deployed to local, not ic since it says that the url is on localhost

yes; are there any “special” rules like ignore certain dfx settings for certain environments?

No, not really, at least not yet. All that is exposed is the env var DFX_NETWORK.

so if there are no special / hidden / hard-coded rules for “local”, why has the candid UI been deployed locally despite of the metadata?
… a few min later …
as it has been deployed on mainnet, too

The metadata does not control whether or not Candid UI gets deployed. Candid UI has no special rights. What matters is if your interface is exposed or not. If it’s exposed Candid UI can read it, just as anyone else. If it’s not exposed you’re good. Go ahead and try to load it up and see what happens

Unprecise lang - mea culpa. The interface is still being published through the candid UI.
I.e. “metadata”: … has no effect.
This topic has not been solved yet.

If dfx --identity anonymous canister metadata <canister id> candid:service --network ic produces the interface, then something didn’t work. Otherwise it’s your browser caching the data

Thanks for this command, Severin.
In a local deployment with “visibility”: “private”, it generates an error; with “visibility”: “public”, it lists the interface. Good results, so far. However, the Candid UI always shows my canister’s interface - even after “delete site data” and “Empty Cache and Hard Reload”. Even in Firefox, which I never used for this before.

Same behavior with the hello canister from the dfinity examples repo - easy to verify.

Thanks very much for your time, Severin. At least I was forced to implement security NOW :wink:

If you deploy only to local then only local changes. You should be able to observe the same on mainnet if you deploy there

Yes, I observe the same behavior on mainnet - The interface of my canister is still being published through the candid UI.