PageSourceSearch

https://opal.ac/assets/js/45b07265.1bcf447b.js

js opal.ac collected 2026-10-04 00:21:41 UTC 8,790 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkdocumentation=globalThis.webpackChunkdocumentation||[]).push([[3868],{695(e,t,n){n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"getting-started/quickstart/docker-compose-config/opal-server","title":"OPAL Server","description":"There are three important concepts in the configuration of the OPAL Server that should be understood.","source":"@site/docs/getting-started/quickstart/docker-compose-config/opal-server.mdx","sourceDirName":"getting-started/quickstart/docker-compose-config","slug":"/getting-started/quickstart/docker-compose-config/opal-server","permalink":"/getting-started/quickstart/docker-compose-config/opal-server","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{},"sidebar":"opalSidebar","previous":{"title":"OPAL Client","permalink":"/getting-started/quickstart/docker-compose-config/opal-client"},"next":{"title":"Overview","permalink":"/getting-started/running-opal/overview"}}');var r=n(1684),o=n(506);const s={},a="OPAL Server",c={},l=[{value:"1. Policy-data basic configuration",id:"1-policy-data-basic-configuration",level:3},{value:"2. Policy-code realtime updates",id:"2-policy-code-realtime-updates",level:3},{value:"3. Policy-data realtime updates",id:"3-policy-data-realtime-updates",level:3}];function d(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"opal-server",children:"OPAL Server"})}),"\n",(0,r.jsx)(t.p,{children:"There are three important concepts in the configuration of the OPAL Server that should be understood."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yml",metastring:"showLineNumbers",children:'services:\n  opal_server:\n    image: permitio/opal-server:latest\n    environment:\n      - OPAL_BROADCAST_URI=postgres://postgres:postgres@broadcast_channel:5432/postgres\n      - UVICORN_NUM_WORKERS=4\n      - OPAL_POLICY_REPO_URL=https://github.com/permitio/opal-example-policy-repo\n      - OPAL_POLICY_REPO_POLLING_INTERVAL=30\n      - OPAL_DATA_CONFIG_SOURCES={"config":{"entries":[{"url":"http://opal_server:7002/policy-data","topics":["policy_data"],"dst_path":"/static"}]}}\n      - OPAL_LOG_FORMAT_INCLUDE_PID=true\n    ports:\n      - "7002:7002"\n    depends_on:\n      - broadcast_channel\n'})}),"\n",(0,r.jsx)(t.h3,{id:"1-policy-data-basic-configuration",children:"1. Policy-data basic configuration"}),"\n",(0,r.jsxs)(t.p,{children:["The OPAL server provides the ",(0,r.jsx)(t.strong,{children:"base data source configuration"})," for the OPAL client. The configuration is structured\nas ",(0,r.jsx)(t.strong,{children:"directives"})," for the client."]}),"\n",(0,r.jsx)(t.p,{children:"Each directive specifies:"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"what to fetch"})," - the URL"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"where to put it in the OPA data document hierarchy"})," - the destination path"]}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["The data sources configured on the server will be fetched ",(0,r.jsx)(t.strong,{children:"by the client"})," every time it decides it needs\nto fetch the entire data configuration. This could be when the client ",(0,r.jsx)(t.strong,{children:"first loads"}),", after a ",(0,r.jsx)(t.strong,{children:"period of\ndisconnection"})," from the server etc."]}),"\n",(0,r.jsxs)(t.p,{children:["The data sources specified in the server configuration must always return a complete and up-to-date picture.\nIn our example ",(0,r.jsx)(t.code,{children:"docker-compose.yml"})," file, the server is configured to return these data sources directives to the client."]}),"\n",(0,r.jsxs)(t.p,{children:["Each data source entry has ",(0,r.jsx)(t.code,{children:"topics"})," to help control which clients should process it.\nThe default topic is ",(0,r.jsx)(t.code,{children:'"policy_data"'})," and is used as a default in both the client (for subscription) and the server (for publishing).\n(If publishing to another topic - make sure the client is subscribed to it by setting the ",(0,r.jsx)(t.code,{children:"OPAL_DATA_TOPICS"})," envar)"]}),"\n",(0,r.jsx)(t.p,{children:"This is what it looks like:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yml",children:'OPAL_DATA_CONFIG_SOURCES={"config":{"entries":[{"url":"http://opal_server:7002/policy-data","topics":["policy_data"],"dst_path":"/static"}]}}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["We fetch the ",(0,r.jsx)(t.code,{children:"/policy-data"})," route on the OPAL server and ",(0,r.jsx)(t.strong,{children:"assign it to the root data document on OPA"})," - ",(0,r.jsx)(t.code,{children:"i.e: /"}),"."]}),"\n",(0,r.jsx)(t.h3,{id:"2-policy-code-realtime-updates",children:"2. Policy-code realtime updates"}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.strong,{children:"OPAL server tracks a git repository"})," and feeds the policy code, or more accurately,\n",(0,r.jsx)(t.code,{children:".rego"})," files along with static data files like ",(0,r.jsx)(t.code,{children:"data.json"})," directly to OPA as a policy."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yml",children:"OPAL_POLICY_REPO_URL=https://github.com/permitio/opal-example-policy-repo\n"})}),"\n",(0,r.jsxs)(t.p,{children:["If new commits will be pushed to this repository that affect ",(0,r.jsx)(t.code,{children:".rego"})," or data files, the updated policy will be pushed\nto OPA automatically in realtime by OPAL."]}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"docker-compose.yml"})," file declares a ",(0,r.jsx)(t.strong,{children:"polling interval"})," to check if new commits are pushed to the repo."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yml",children:"OPAL_POLICY_REPO_POLLING_INTERVAL=30\n"})}),"\n",(0,r.jsxs)(t.admonition,{type:"tip",children:[(0,r.jsxs)(t.p,{children:["When working in a ",(0,r.jsx)(t.strong,{children:"production environment"}),", we recommend you setup a ",(0,r.jsx)(t.strong,{children:"git webhook"})," from your repo to the OPAL server."]}),(0,r.jsxs)(t.p,{children:["The only reason we are using polling here is because we want the example ",(0,r.jsx)(t.code,{children:"docker-compose.yml"})," file to work for you as well,\nand webhooks can only hit a public internet address."]}),(0,r.jsxs)(t.p,{children:["If you are working in a ",(0,r.jsx)(t.strong,{children:"development environment"}),", you can use a reverse proxy like ",(0,r.jsx)(t.a,{href:"https://ngrok.com/",children:"ngrok"}),"."]})]}),"\n",(0,r.jsx)(t.h3,{id:"3-policy-data-realtime-updates",children:"3. Policy-data realtime updates"}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.strong,{children:"OPAL server can push realtime data updates to the client"}),". It offers a ",(0,r.jsx)(t.strong,{children:"REST API"})," that allows you to push updates\nvia the server using a pub/sub channel."]}),"\n",(0,r.jsx)(t.p,{children:"Below is an example why realtime updates are important."}),"\n",(0,r.jsx)(t.admonition,{title:"EXAMPLE",type:"info",children:(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Alice just ",(0,r.jsx)(t.strong,{children:"invited"})," Bob to a google drive document."]}),"\n",(0,r.jsxs)(t.li,{children:["Bob expects to be able to ",(0,r.jsx)(t.strong,{children:"view the document immediately"}),"."]}),"\n",(0,r.jsxs)(t.li,{children:["If your authorization layer is implemented with OPA, ",(0,r.jsx)(t.strong,{children:"you cannot wait for the OPA agent to download a new bundle"}),",\nit's too slow for live application."]}),"\n",(0,r.jsxs)(t.li,{children:["Instead you ",(0,r.jsx)(t.strong,{children:"push an update via OPAL"})," and the state of the OPA agent changes immediately."]}),"\n"]})}),"\n",(0,r.jsxs)(t.p,{children:["If you want to learn more about triggering realtime updates via OPAL - please refer\nto ",(0,r.jsx)(t.a,{href:"/tutorials/trigger_data_updates",children:(0,r.jsx)(t.strong,{children:"this"})})," guide."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},506(e,t,n){n.d(t,{R:()=>s,x:()=>a});var i=n(2888);const r={},o=i.createContext(r);function s(e){const t=i.useContext(o);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.