mirror of
https://github.com/kemko/reproxy.git
synced 2026-01-06 10:15:47 +03:00
107 lines
38 KiB
HTML
107 lines
38 KiB
HTML
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Reproxy</title><link rel="icon" href="/favicon.svg"><link rel="mask-icon" href="/favicon.svg" color="#FF7A00"><link rel="apple-touch-icon" href="/touch-icon.png"><meta name="theme-color" content="#FF7A00"><meta property="og:title" content="Reproxy"><meta name="description" content="Reproxy is a minimalistic system acting as an edge server / reverse proxy for your infrastructure. It provides the only essential functionality with no bells and whistles. Setup is very straightforward and not much to configure."><meta property="og:description" content="Reproxy is a minimalistic system acting as an edge server / reverse proxy for your infrastructure. It provides the only essential functionality with no bells and whistles. Setup is very straightforward and not much to configure."><meta property="og:image" content="https://reproxy.io/sharing.png"><meta property="og:image:width" content="1080"><meta property="og:image:height" content="512"><meta property="twitter:image" content="https://reproxy.io/sharing.png"><meta property="og:type" content="website"><meta property="og:url" content="https://reproxy.io"><meta property="og:locale" content="en_US"><meta name="twitter:card" content="summary_large_image"><style>/*! tailwindcss v2.1.1 | MIT License | https://tailwindcss.com*//*! modern-normalize v1.0.0 | MIT License | https://github.com/sindresorhus/modern-normalize */:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;margin:0}hr{color:inherit;height:0}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:transparent;background-image:none}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{font-family:inherit;line-height:inherit}*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{color:inherit;line-height:inherit;padding:0}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}*{--tw-shadow:0 0 transparent;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent}.prose{color:#374151;max-width:100%}.prose [class~=lead]{color:#4b5563;font-size:1.25em;line-height:1.6;margin-bottom:1.2em;margin-top:1.2em}.prose a{color:#111827;font-weight:500;text-decoration:underline}.prose strong{color:#111827;font-weight:600}.prose ol[type=A]{--list-counter-style:upper-alpha}.prose ol[type=a]{--list-counter-style:lower-alpha}.prose ol[type="A s"]{--list-counter-style:upper-alpha}.prose ol[type="a s"]{--list-counter-style:lower-alpha}.prose ol[type=I]{--list-counter-style:upper-roman}.prose ol[type=i]{--list-counter-style:lower-roman}.prose ol[type="I s"]{--list-counter-style:upper-roman}.prose ol[type="i s"]{--list-counter-style:lower-roman}.prose ol[type="1"]{--list-counter-style:decimal}.prose ol>li{padding-left:1.75em;position:relative}.prose ol>li:before{color:#6b7280;content:counter(list-item,var(--list-counter-style,decimal)) ".";font-weight:400;left:0;position:absolute}.prose ul>li{padding-left:1.75em;position:relative}.prose ul>li:before{background-color:#d1d5db;border-radius:50%;content:"";height:.375em;left:.25em;position:absolute;top:.6875em;width:.375em}.prose hr{border-color:#e5e7eb;border-top-width:2px;margin-bottom:3em;margin-top:3em}.prose blockquote{border-left-color:#e5e7eb;border-left-width:.25rem;color:#111827;font-style:italic;font-weight:500;margin-bottom:1.6em;margin-top:1.6em;padding-left:1em;quotes:"\201C""\201D""\2018""\2019"}.prose h1{color:#111827;font-size:2.25em;font-weight:800;line-height:1.1111111;margin-bottom:.8888889em;margin-top:0}.prose h2{color:#111827;font-size:1.5em;font-weight:700;line-height:1.3333333;margin-bottom:1em;margin-top:2em}.prose h3{color:#111827;font-size:1.25em;font-weight:600;line-height:1.6;margin-bottom:.6em;margin-top:1.6em}.prose h4{color:#111827;font-weight:600;line-height:1.5;margin-bottom:.5em;margin-top:1.5em}.prose figure figcaption{color:#6b7280;font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose code{word-wrap:break-word;background-color:#f3f4f6;border-radius:.25rem;color:#374151;font-size:.875em;font-weight:400;padding:.125rem .5rem}.prose a code{color:#111827}.prose pre{background-color:#1f2937;border-radius:.375rem;color:#e5e7eb;font-size:.875em;line-height:1.7142857;margin-bottom:1.7142857em;margin-top:1.7142857em;overflow-x:auto;padding:.8571429em 1.1428571em}.prose pre code{background-color:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;font-weight:400;line-height:inherit;padding:0}.prose pre code:after,.prose pre code:before{content:none}.prose table{font-size:.875em;line-height:1.7142857;margin-bottom:2em;margin-top:2em;table-layout:auto;text-align:left;width:100%}.prose thead{border-bottom-color:#d1d5db;border-bottom-width:1px;color:#111827;font-weight:600}.prose thead th{padding-bottom:.5714286em;padding-left:.5714286em;padding-right:.5714286em;vertical-align:bottom}.prose tbody tr{border-bottom-color:#e5e7eb;border-bottom-width:1px}.prose tbody tr:last-child{border-bottom-width:0}.prose tbody td{padding:.5714286em;vertical-align:top}.prose{font-size:1rem;line-height:1.5}.prose p{margin-bottom:1.25em;margin-top:1.25em}.prose img{display:initial;margin:.5rem}.prose figure,.prose video{margin-bottom:2em;margin-top:2em}.prose figure>*{margin-bottom:0;margin-top:0}.prose h2 code{font-size:.875em}.prose h3 code{font-size:.9em}.prose ol,.prose ul{margin-bottom:1.25em;margin-top:1.25em}.prose li{margin-bottom:.5em;margin-top:.5em}.prose>ul>li p{margin-bottom:.75em;margin-top:.75em}.prose>ul>li>:first-child{margin-top:1.25em}.prose>ul>li>:last-child{margin-bottom:1.25em}.prose>ol>li>:first-child{margin-top:1.25em}.prose>ol>li>:last-child{margin-bottom:1.25em}.prose ol ol,.prose ol ul,.prose ul ol,.prose ul ul{margin-bottom:.75em;margin-top:.75em}.prose h2+*,.prose h3+*,.prose h4+*,.prose hr+*{margin-top:0}.prose thead th:first-child{padding-left:0}.prose thead th:last-child{padding-right:0}.prose tbody td:first-child{padding-left:0}.prose tbody td:last-child{padding-right:0}.prose>:first-child{margin-top:0}.prose>:last-child{margin-bottom:0}.prose{padding-left:3rem;padding-right:3rem}.prose h2,.prose h3,.prose h4{margin-top:-3rem;padding-top:6rem}.fixed{position:fixed}.inset-y-0{bottom:0;top:0}.top-0{top:0}.left-0{left:0}.z-20{z-index:20}.z-10{z-index:10}.float-right{float:right}.m-auto{margin:auto}.mb-2{margin-bottom:.5rem}.mr-auto{margin-right:auto}.mt-1{margin-top:.25rem}.mr-3{margin-right:.75rem}.mt-20{margin-top:5rem}.-mr-4{margin-right:-1rem}.mt-4{margin-top:1rem}.ml-auto{margin-left:auto}.ml-2{margin-left:.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-screen{height:100vh}.h-16{height:4rem}.w-full{width:100%}.max-w-full{max-width:100%}.max-w-5xl{max-width:64rem}.items-center{align-items:center}.justify-end{justify-content:flex-end}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-gray-100{--tw-border-opacity:1;border-color:rgba(243,244,246,var(--tw-border-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.bg-opacity-75{--tw-bg-opacity:0.75}.p-1{padding:.25rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-0{padding:0}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.px-4{padding-left:1rem;padding-right:1rem}.pl-5{padding-left:1.25rem}.pr-6{padding-right:1.5rem}.pl-1{padding-left:.25rem}.pt-24{padding-top:6rem}.pb-20{padding-bottom:5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-normal{font-weight:400}.text-black{--tw-text-opacity:1;color:rgba(0,0,0,var(--tw-text-opacity))}.text-orange-600{--tw-text-opacity:1;color:rgba(234,88,12,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgba(243,244,246,var(--tw-text-opacity))}.no-underline{text-decoration:none}.backdrop-filter{--tw-backdrop-blur:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-brightness:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-contrast:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-grayscale:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-hue-rotate:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-invert:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-opacity:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-saturate:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-sepia:var(--tw-empty,/*!*/ /*!*/);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px)}.transition-colors{transition-duration:.15s;transition-property:background-color,border-color,color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-200{transition-duration:.2s}html{scroll-behavior:smooth}.docs-nav a~ul{margin-bottom:.5rem;margin-top:.25rem}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgba(17,24,39,var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}@media (prefers-color-scheme:dark){.dark\:prose-dark{color:#9ca3af}.dark\:prose-dark [class~=lead]{color:#d1d5db}.dark\:prose-dark a,.dark\:prose-dark strong{color:#e5e7eb}.dark\:prose-dark ol>li:before{color:#9ca3af}.dark\:prose-dark ul>li:before{background-color:#4b5563}.dark\:prose-dark hr{border-color:#6b7280}.dark\:prose-dark blockquote{border-left-color:#4b5563;color:#d1d5db}.dark\:prose-dark h1,.dark\:prose-dark h2,.dark\:prose-dark h3,.dark\:prose-dark h4{color:#e5e7eb}.dark\:prose-dark figure figcaption{color:#9ca3af}.dark\:prose-dark code{background-color:#374151;color:#e5e7eb}.dark\:prose-dark a code{color:#e5e7eb}.dark\:prose-dark pre{background-color:#1f2937;color:#d1d5db}.dark\:prose-dark thead{border-bottom-color:#9ca3af;color:#e5e7eb}.dark\:prose-dark tbody tr{border-bottom-color:#4b5563}.dark\:border-gray-800{--tw-border-opacity:1;border-color:rgba(31,41,55,var(--tw-border-opacity))}.dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgba(17,24,39,var(--tw-bg-opacity))}.dark\:bg-gray-500{--tw-bg-opacity:1;background-color:rgba(107,114,128,var(--tw-bg-opacity))}.dark\:text-white{--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.dark\:text-gray-300{--tw-text-opacity:1;color:rgba(209,213,219,var(--tw-text-opacity))}.dark\:text-gray-400{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.dark\:text-gray-100{--tw-text-opacity:1;color:rgba(243,244,246,var(--tw-text-opacity))}.dark\:hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgba(229,231,235,var(--tw-text-opacity))}}@media (min-width:640px){.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width:768px){.md\:mt-20{margin-top:5rem}.md\:block{display:block}.md\:hidden{display:none}.md\:h-20{height:5rem}.md\:w-60{width:15rem}.md\:px-16{padding-left:4rem;padding-right:4rem}.md\:pt-28{padding-top:7rem}.md\:pl-60{padding-left:15rem}}@media (min-width:1024px){.lg\:px-24{padding-left:6rem;padding-right:6rem}}@media (min-width:1536px){.\32xl\:prose-lg{font-size:1.125rem;line-height:1.5}.\32xl\:prose-lg p{margin-bottom:1.3333333em;margin-top:1.3333333em}.\32xl\:prose-lg [class~=lead]{font-size:1.2222222em;line-height:1.4545455;margin-bottom:1.0909091em;margin-top:1.0909091em}.\32xl\:prose-lg blockquote{margin-bottom:1.6666667em;margin-top:1.6666667em;padding-left:1em}.\32xl\:prose-lg h1{font-size:2.6666667em;line-height:1;margin-bottom:.8333333em;margin-top:0}.\32xl\:prose-lg h2{font-size:1.6666667em;line-height:1.3333333;margin-bottom:1.0666667em;margin-top:1.8666667em}.\32xl\:prose-lg h3{font-size:1.3333333em;line-height:1.5;margin-bottom:.6666667em;margin-top:1.6666667em}.\32xl\:prose-lg h4{line-height:1.5555556;margin-bottom:.4444444em;margin-top:1.7777778em}.\32xl\:prose-lg figure,.\32xl\:prose-lg img,.\32xl\:prose-lg video{margin-bottom:1.7777778em;margin-top:1.7777778em}.\32xl\:prose-lg figure>*{margin-bottom:0;margin-top:0}.\32xl\:prose-lg figure figcaption{font-size:.8888889em;line-height:1.5;margin-top:1em}.\32xl\:prose-lg code{font-size:.8888889em}.\32xl\:prose-lg h2 code{font-size:.8666667em}.\32xl\:prose-lg h3 code{font-size:.875em}.\32xl\:prose-lg pre{border-radius:.375rem;font-size:.8888889em;line-height:1.75;margin-bottom:2em;margin-top:2em;padding:1em 1.5em}.\32xl\:prose-lg ol,.\32xl\:prose-lg ul{margin-bottom:1.3333333em;margin-top:1.3333333em}.\32xl\:prose-lg li{margin-bottom:.6666667em;margin-top:.6666667em}.\32xl\:prose-lg ol>li{padding-left:1.6666667em}.\32xl\:prose-lg ol>li:before{left:0}.\32xl\:prose-lg ul>li{padding-left:1.6666667em}.\32xl\:prose-lg ul>li:before{height:.3333333em;left:.2222222em;top:.72222em;width:.3333333em}.\32xl\:prose-lg>ul>li p{margin-bottom:.8888889em;margin-top:.8888889em}.\32xl\:prose-lg>ul>li>:first-child{margin-top:1.3333333em}.\32xl\:prose-lg>ul>li>:last-child{margin-bottom:1.3333333em}.\32xl\:prose-lg>ol>li>:first-child{margin-top:1.3333333em}.\32xl\:prose-lg>ol>li>:last-child{margin-bottom:1.3333333em}.\32xl\:prose-lg ol ol,.\32xl\:prose-lg ol ul,.\32xl\:prose-lg ul ol,.\32xl\:prose-lg ul ul{margin-bottom:.8888889em;margin-top:.8888889em}.\32xl\:prose-lg hr{margin-bottom:3.1111111em;margin-top:3.1111111em}.\32xl\:prose-lg h2+*,.\32xl\:prose-lg h3+*,.\32xl\:prose-lg h4+*,.\32xl\:prose-lg hr+*{margin-top:0}.\32xl\:prose-lg table{font-size:.8888889em;line-height:1.5}.\32xl\:prose-lg thead th{padding-bottom:.75em;padding-left:.75em;padding-right:.75em}.\32xl\:prose-lg thead th:first-child{padding-left:0}.\32xl\:prose-lg thead th:last-child{padding-right:0}.\32xl\:prose-lg tbody td{padding:.75em}.\32xl\:prose-lg tbody td:first-child{padding-left:0}.\32xl\:prose-lg tbody td:last-child{padding-right:0}.\32xl\:prose-lg>:first-child{margin-top:0}.\32xl\:prose-lg>:last-child{margin-bottom:0}.\32xl\:prose-lg h2,.\32xl\:prose-lg h3,.\32xl\:prose-lg h4{margin-top:-3rem;padding-top:6rem}}</style></head><body class="h-screen bg-white dark:bg-gray-900"><header class="fixed top-0 left-0 z-20 w-full border-b border-gray-100 bg-opacity-75 backdrop-filter backdrop-blur-lg bg-white dark:bg-gray-900 transition-colors duration-200 dark:bg-dark dark:border-gray-800"><nav class="flex items-center h-16 md:h-20 w-full py-2"><div class="p-4 mr-auto"><span class="text-xl font-bold text-orange-600 dark:text-gray-300">Reproxy</span> <span class="block mt-1 text-sm md:text-md text-gray-500 dark:text-gray-400">Simple Reverse Proxy</span></div><div class="mr-3"><a class="text-gray-400 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-200" aria-label="github link" rel="noopener noreferrer" href="https://github.com/umputun/reproxy" target="_blank"><svg height="36" viewBox="0 0 24 24" fill="none"><path d="M12 3C7.0275 3 3 7.12937 3 12.2276C3 16.3109 5.57625 19.7597 9.15374 20.9824C9.60374 21.0631 9.77249 20.7863 9.77249 20.5441C9.77249 20.3249 9.76125 19.5982 9.76125 18.8254C7.5 19.2522 6.915 18.2602 6.735 17.7412C6.63375 17.4759 6.19499 16.6569 5.8125 16.4378C5.4975 16.2647 5.0475 15.838 5.80124 15.8264C6.51 15.8149 7.01625 16.4954 7.18499 16.7723C7.99499 18.1679 9.28875 17.7758 9.80625 17.5335C9.885 16.9337 10.1212 16.53 10.38 16.2993C8.3775 16.0687 6.285 15.2728 6.285 11.7432C6.285 10.7397 6.63375 9.9092 7.20749 9.26326C7.1175 9.03257 6.8025 8.08674 7.2975 6.81794C7.2975 6.81794 8.05125 6.57571 9.77249 7.76377C10.4925 7.55615 11.2575 7.45234 12.0225 7.45234C12.7875 7.45234 13.5525 7.55615 14.2725 7.76377C15.9937 6.56418 16.7475 6.81794 16.7475 6.81794C17.2424 8.08674 16.9275 9.03257 16.8375 9.26326C17.4113 9.9092 17.76 10.7281 17.76 11.7432C17.76 15.2843 15.6563 16.0687 13.6537 16.2993C13.98 16.5877 14.2613 17.1414 14.2613 18.0065C14.2613 19.2407 14.25 20.2326 14.25 20.5441C14.25 20.7863 14.4188 21.0746 14.8688 20.9824C16.6554 20.364 18.2079 19.1866 19.3078 17.6162C20.4077 16.0457 20.9995 14.1611 21 12.2276C21 7.12937 16.9725 3 12 3Z" fill="currentColor"></path></svg></a></div><button aria-label="Show navigation" id="sidebar-open-button" class="block md:hidden mr-3"><svg fill="none" width="24" height="24" viewBox="0 0 24 24" class="text-gray-400 hover:text-gray-600" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg></button></nav></header><aside id="sidebar" class="hidden md:block fixed z-10 top-0 left-0 inset-y-0 w-full md:w-60 overflow-y-auto mt-20 md:mt-20 bg-white dark:bg-gray-900 text-gray-500 dark:text-gray-400 border-r border-gray-100 dark:bg-dark dark:border-gray-800 transition-colors duration-200"><button name="Close navigation" id="sidebar-close-button" class="float-right justify-end block md:hidden -mr-4 p-6"><svg xmlns="http://www.w3.org/2000/svg" class="dark:bg-gray-500" width="18" height="18" viewBox="0 0 18 18"><path class="text-gray-100" d="M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z"></path></svg></button><div class="py-6 pr-6 pl-1"><nav class="docs-nav" role="navigation" aria-label="Table of contents"><ul class="pl-5"><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#install">Install</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#providers">Providers</a><ul class="pl-5"><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#static">Static</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#file">File</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#docker">Docker</a></li></ul></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#ssl-support">SSL support</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#logging">Logging</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#assets-server">Assets Server</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#more-options">More options</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#ping-and-health-checks">Ping and health checks</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#all-application-options">All Application Options</a></li><li class="mb-2"><a class="inline-block p-1 hover:text-gray-900 dark:hover:text-gray-200" href="#status">Status</a></li></ul></nav></div></aside><main class="px-4 pt-24 md:pt-28 pb-20 md:pl-60"><arcicle class="block p-0 sm:px-6 md:px-16 lg:px-24 m-auto max-w-5xl prose 2xl:prose-lg dark:prose-dark dark:text-gray-100"><div align="center"><svg class="max-w-full text-black dark:text-white" width="355px" fill="none" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 710 260"><path d="M0 124l85-34v145L0 124z" fill="#FF7A00"/><path d="M170 136l-85 34V25l85 111z" fill="#FFB35A"/><path d="M208 181h23v-28h8l15 28h25l-18-32c9-4 15-12 15-24 0-17-13-28-32-28h-36v84zm23-46v-20h8c8 0 13 3 13 10 0 8-5 10-13 10h-8zM315 182c17 0 29-9 31-22h-21c-1 4-5 6-10 6-7 0-10-5-10-11v-1h41v-5c0-20-13-32-32-32s-32 13-32 32c0 21 12 33 33 33zm-10-40c0-5 4-9 10-9 5 0 10 4 10 9h-20zM355 204h23v-34c3 7 9 11 18 11 13 0 25-10 25-32s-13-32-25-32c-10 0-15 5-18 12v-11h-23v86zm22-55c0-9 4-15 10-15 7 0 10 6 10 15s-3 15-10 15c-6 0-10-6-10-15zM430 181h23v-33c0-7 5-12 11-12l9 1v-19l-6-1c-7 0-12 4-14 13h-1v-12h-22v63zM507 182c21 0 33-13 33-33 0-19-12-32-33-32-20 0-33 13-33 32 0 20 13 33 33 33zm0-17c-6 0-9-6-9-16s3-16 9-16 10 6 10 16-4 16-10 16zM567 118h-23l17 31-18 32h23l10-20 11 20h22l-18-32 17-31h-22l-10 19-9-19zM630 204c16 0 23-8 27-18l23-68h-24l-10 43h-1l-10-43h-24l22 65v1c-2 4-6 4-12 2l-5 16 14 2z" fill="currentColor" class="logo-text"/></svg></div><p>Reproxy is a simple edge HTTP(s) server / reverse proxy supporting various providers (docker, static, file).<br>One or more providers supply information about requested server, requested url, destination url and health check url.<br>Distributed as a single binary or as a docker container.</p><ul><li>Automatic SSL termination with <a href="https://letsencrypt.org/" rel="nofollow noopener noreferrer" target="_blank">Let's Encrypt</a></li><li>Support of user-provided SSL certificates</li><li>Simple but flexible proxy rules</li><li>Static, command line proxy rules provider</li><li>Dynamic, file-based proxy rules provider</li><li>Docker provider with an automatic discovery</li><li>Optional traffic compression</li><li>User-defined limits and timeouts</li><li>Single binary distribution</li><li>Docker container distribution</li><li>Built-in static assets server</li></ul><hr><p><a href="https://github.com/umputun/reproxy/actions/workflows/ci.yml"><img src="https://github.com/umputun/reproxy/actions/workflows/ci.yml/badge.svg" alt="build"></a> <a href="https://coveralls.io/github/umputun/reproxy?branch=master"><img src="https://coveralls.io/repos/github/umputun/reproxy/badge.svg?branch=master" alt="Coverage Status"></a> <a href="https://goreportcard.com/report/github.com/umputun/reproxy"><img src="https://goreportcard.com/badge/github.com/umputun/reproxy" alt="Go Report Card"></a> <a href="https://hub.docker.com/repository/docker/umputun/reproxy"><img src="https://img.shields.io/docker/automated/jrottenberg/ffmpeg.svg" alt="Docker Automated build"></a></p><p>Server can be set as FQDN, i.e. <code>s.example.com</code> or <code>*</code> (catch all). Requested url can be regex, for example <code>^/api/(.*)</code> and destination url may have regex matched groups in, i.e. <code>http://d.example.com:8080/$1</code>. For the example above <code>http://s.example.com/api/something?foo=bar</code> will be proxied to <code>http://d.example.com:8080/something?foo=bar</code>.</p><p>For convenience, requests with the trailing <code>/</code> and without regex groups expanded to <code>/(.*)</code>, and destinations in those cases expanded to <code>/$1</code>. I.e. <code>/api/</code> -> <code>http://127.0.0.1/service</code> will be translated to <code>^/api/(.*)</code> -> <code>http://127.0.0.1/service/$1</code></p><p>Both HTTP and HTTPS supported. For HTTPS, static certificate can be used as well as automated ACME (Let's Encrypt) certificates. Optional assets server can be used to serve static files.</p><p>Starting reproxy requires at least one provider defined. The rest of parameters are strictly optional and have sane default.</p><p>Example with a static provider:<br><code>reproxy --static.enabled --static.rule="example.com/api/(.*),https://api.example.com/$1"</code><br>Example with an automatic docker discovery:<br><code>reproxy --docker.enabled --docker.auto</code></p><h2 id="install">Install <a href="#install"></a></h2><ul><li>for a binary distribution pick the proper file in the <a href="https://github.com/umputun/reproxy/releases">release section</a></li><li>docker container available on <a href="https://hub.docker.com/r/umputun/reproxy">Docker Hub</a> as well as on <a href="ghcr.io/umputun/reproxy">Github Container Registry</a>.</li></ul><p>Latest stable version has <code>:vX.Y.Z</code> tag (with <code>:latest</code> alias) and the current master has <code>:master</code> tag.</p><h2 id="providers">Providers <a href="#providers"></a></h2><p>User can sets multiple providers at the same time.<br><em>See examples of various providers in <a href="https://github.com/umputun/reproxy/tree/master/examples">examples</a></em></p><h3 id="static">Static <a href="#static"></a></h3><p>This is the simplest provider defining all mapping rules directly in the command line (or environment). Multiple rules supported.<br>Each rule is 3 or 4 comma-separated elements <code>server,sourceurl,destination,[ping-url]</code>. For example:</p><ul><li><code>*,^/api/(.*),https://api.example.com/$1,</code> - proxy all request to any host/server with <code>/api</code> prefix to <code>https://api.example.com</code></li><li><code>example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping</code> - proxy all requests to <code>example.com</code> and with <code>/foo/bar</code> url to <code>https://api.example.com/zzz</code>. Uses <code>https://api.example.com/ping</code> for the health check</li></ul><p>The last (4th) element defines an optional ping url used for health reporting. I.e.<code>*,^/api/(.*),https://api.example.com/$1,https://api.example.com/ping</code>. See <a href="https://github.com/umputun/reproxy#ping-and-health-checks">Health check</a> section for more details.</p><h3 id="file">File <a href="#file"></a></h3><p><code>reproxy --file.enabled --file.name=config.yml</code></p><p>Example of <code>config.yml</code>:</p><pre><code class="language-yaml">default: # the same as * (catch-all) server
|
||
- { route: "^/api/svc1/(.*)", dest: "http://127.0.0.1:8080/blah1/$1" }
|
||
- {
|
||
route: "/api/svc3/xyz",
|
||
dest: "http://127.0.0.3:8080/blah3/xyz",
|
||
"ping": "http://127.0.0.3:8080/ping",
|
||
}
|
||
srv.example.com:
|
||
- { route: "^/api/svc2/(.*)", dest: "http://127.0.0.2:8080/blah2/$1/abc" }
|
||
</code></pre><p>This is a dynamic provider and file change will be applied automatically.</p><h3 id="docker">Docker <a href="#docker"></a></h3><p>Docker provider supports a fully automatic discovery (with <code>--docker.auto</code>) with no extra configuration and by default redirects all requests like <code>https://server/<container_name>/(.*)</code> to the internal IP of the given container and the exposed port. Only active (running) containers will be detected.</p><p>This default can be changed with labels:</p><ul><li><code>reproxy.server</code> - server (hostname) to match. Also can be a list of comma-separated servers.</li><li><code>reproxy.route</code> - source route (location)</li><li><code>reproxy.dest</code> - destination path. Note: this is not full url, but just the path which will be appended to container's ip:port</li><li><code>reproxy.port</code> - destination port for the discovered container</li><li><code>reproxy.ping</code> - ping path for the destination container.</li><li><code>reproxy.enabled</code> - enable (<code>yes</code>, <code>true</code>, <code>1</code>) or disable (<code>no</code>, <code>false</code>, <code>0</code>) container from reproxy destinations.</li></ul><p>Pls note: without <code>--docker.auto</code> the destination container has to have at least one of <code>reproxy.*</code> labels to be considered as a potential destination.</p><p>With <code>--docker.auto</code>, all containers with exposed port will be considered as routing destinations. There are 3 ways to restrict it:</p><ul><li>Exclude some containers explicitly with <code>--docker.exclude</code>, i.e. <code>--docker.exclude=c1 --docker.exclude=c2 ...</code></li><li>Allow only a particular docker network with <code>--docker.network</code></li><li>Set the label <code>reproxy.enabled=false</code> or <code>reproxy.enabled=no</code> or <code>reproxy.enabled=0</code></li></ul><p>This is a dynamic provider and any change in container's status will be applied automatically.</p><h2 id="ssl-support">SSL support <a href="#ssl-support"></a></h2><p>SSL mode (by default none) can be set to <code>auto</code> (ACME/LE certificates), <code>static</code> (existing certificate) or <code>none</code>. If <code>auto</code> turned on SSL certificate will be issued automatically for all discovered server names. User can override it by setting <code>--ssl.fqdn</code> value(s)</p><h2 id="logging">Logging <a href="#logging"></a></h2><p>By default no request log generated. This can be turned on by setting <code>--logger.enabled</code>. The log (auto-rotated) has <a href="http://httpd.apache.org/docs/2.2/logs.html#combined">Apache Combined Log Format</a></p><p>User can also turn stdout log on with <code>--logger.stdout</code>. It won't affect the file logging but will output some minimal info about processed requests, something like this:</p><pre><code>2021/04/16 01:17:25.601 [INFO] GET - /echo/image.png - xxx.xxx.xxx.xxx - 200 (155400) - 371.661251ms
|
||
2021/04/16 01:18:18.959 [INFO] GET - /api/v1/params - xxx.xxx.xxx.xxx - 200 (74) - 1.217669m
|
||
</code></pre><h2 id="assets-server">Assets Server <a href="#assets-server"></a></h2><p>User may turn assets server on (off by default) to serve static files. As long as <code>--assets.location</code> set it will treat every non-proxied request under <code>assets.root</code> as a request for static files. Assets server can be used without any proxy providers. In this mode reproxy acts as a simple web server for a static context.</p><p>In addition to the common assets server multiple custom static servers supported. Each provider has a different way to define such static rule and some providers may not support it at all. For example, multiple static server make sense in case of static (command line provide), file provider and can be even useful with docker provider.</p><ol><li>static provider - if source element prefixed by <code>assets:</code> it will be treated as file-server. For example <code>*,assets:/web,/var/www,</code> will serve all <code>/web/*</code> request with a file server on top of <code>/var/www</code> directory.</li><li>file provider - setting optional field <code>assets: true</code></li><li>docker provider - <code>reproxy.assets=web-root:location</code>, i.e. <code>reproxy.assets=/web:/var/www</code>.</li></ol><h2 id="more-options">More options <a href="#more-options"></a></h2><ul><li><code>--gzip</code> enables gizp compression for responses.</li><li><code>--max=N</code> allows to set the maximum size of request (default 64k)</li><li><code>--header</code> sets extra header(s) added to each proxied request</li><li><code>--timeout.*</code> various timeouts for both server and proxy transport. See <code>timeout</code> section in <a href="#all-application-options">All Application Options</a></li></ul><h2 id="ping-and-health-checks">Ping and health checks <a href="#ping-and-health-checks"></a></h2><p>reproxy provides 2 endpoints for this purpose:</p><ul><li><code>/ping</code> responds with <code>pong</code> and indicates what reproxy up and running</li><li><code>/health</code> returns <code>200 OK</code> status if all destination servers responded to their ping request with <code>200</code> or <code>417 Expectation Failed</code> if any of servers responded with non-200 code. It also returns json body with details about passed/failed services.</li></ul><h2 id="all-application-options">All Application Options <a href="#all-application-options"></a></h2><pre><code> -l, --listen= listen on host:port (default: 127.0.0.1:8080) [$LISTEN]
|
||
-m, --max= max response size (default: 64000) [$MAX_SIZE]
|
||
-g, --gzip enable gz compression [$GZIP]
|
||
-x, --header= proxy headers [$HEADER]
|
||
--signature enable reproxy signature headers [$SIGNATURE]
|
||
--dbg debug mode [$DEBUG]
|
||
|
||
ssl:
|
||
--ssl.type=[none|static|auto] ssl (auto) support (default: none) [$SSL_TYPE]
|
||
--ssl.cert= path to cert.pem file [$SSL_CERT]
|
||
--ssl.key= path to key.pem file [$SSL_KEY]
|
||
--ssl.acme-location= dir where certificates will be stored by autocert manager (default: ./var/acme) [$SSL_ACME_LOCATION]
|
||
--ssl.acme-email= admin email for certificate notifications [$SSL_ACME_EMAIL]
|
||
--ssl.http-port= http port for redirect to https and acme challenge test (default: 80) [$SSL_HTTP_PORT]
|
||
--ssl.fqdn= FQDN(s) for ACME certificates [$SSL_ACME_FQDN]
|
||
|
||
assets:
|
||
-a, --assets.location= assets location [$ASSETS_LOCATION]
|
||
--assets.root= assets web root (default: /) [$ASSETS_ROOT]
|
||
|
||
logger:
|
||
--logger.stdout enable stdout logging [$LOGGER_STDOUT]
|
||
--logger.enabled enable access and error rotated logs [$LOGGER_ENABLED]
|
||
--logger.file= location of access log (default: access.log) [$LOGGER_FILE]
|
||
--logger.max-size= maximum size in megabytes before it gets rotated (default: 100) [$LOGGER_MAX_SIZE]
|
||
--logger.max-backups= maximum number of old log files to retain (default: 10) [$LOGGER_MAX_BACKUPS]
|
||
|
||
docker:
|
||
--docker.enabled enable docker provider [$DOCKER_ENABLED]
|
||
--docker.host= docker host (default: unix:///var/run/docker.sock) [$DOCKER_HOST]
|
||
--docker.network= docker network [$DOCKER_NETWORK]
|
||
--docker.exclude= excluded containers [$DOCKER_EXCLUDE]
|
||
--docker.auto enable automatic routing (without labels) [$DOCKER_AUTO]
|
||
|
||
file:
|
||
--file.enabled enable file provider [$FILE_ENABLED]
|
||
--file.name= file name (default: reproxy.yml) [$FILE_NAME]
|
||
--file.interval= file check interval (default: 3s) [$FILE_INTERVAL]
|
||
--file.delay= file event delay (default: 500ms) [$FILE_DELAY]
|
||
|
||
static:
|
||
--static.enabled enable static provider [$STATIC_ENABLED]
|
||
--static.rule= routing rules [$STATIC_RULES]
|
||
|
||
timeout:
|
||
--timeout.read-header= read header server timeout (default: 5s) [$TIMEOUT_READ_HEADER]
|
||
--timeout.write= write server timeout (default: 30s) [$TIMEOUT_WRITE]
|
||
--timeout.idle= idle server timeout (default: 30s) [$TIMEOUT_IDLE]
|
||
--timeout.dial= dial transport timeout (default: 30s) [$TIMEOUT_DIAL]
|
||
--timeout.keep-alive= keep-alive transport timeout (default: 30s) [$TIMEOUT_KEEP_ALIVE]
|
||
--timeout.resp-header= response header transport timeout (default: 5s) [$TIMEOUT_RESP_HEADER]
|
||
--timeout.idle-conn= idle connection transport timeout (default: 90s) [$TIMEOUT_IDLE_CONN]
|
||
--timeout.tls= TLS hanshake transport timeout (default: 10s) [$TIMEOUT_TLS]
|
||
--timeout.continue= expect continue transport timeout (default: 1s) [$TIMEOUT_CONTINUE]
|
||
|
||
Help Options:
|
||
-h, --help Show this help message
|
||
|
||
</code></pre><h2 id="status">Status <a href="#status"></a></h2><p>The project is under active development and may have breaking changes till <code>v1</code> released.</p><footer class="flex mt-4"><div class="ml-auto text-xs">Updated <time datetime="2021-15-17">Apr 17, 2021</time> <a class="ml-2 inline-block no-underline font-normal rounded" target="_blank" href="https://github.com/umputun/reproxy/edit/master/README.md">Edit</a></div></footer></arcicle></main><script>const sidebarElement = document.getElementById('sidebar')
|
||
const sidebarOpenButton = document.getElementById('sidebar-open-button')
|
||
const sidebarCloseButton = document.getElementById('sidebar-close-button')
|
||
const sidebarLinks = sidebarElement.querySelectorAll('a')
|
||
|
||
sidebarOpenButton.addEventListener('click', toggleSidebar)
|
||
sidebarCloseButton.addEventListener('click', closeSidebar)
|
||
|
||
Array.from(sidebarLinks).forEach((l) => {
|
||
l.addEventListener('click', () => {
|
||
if (!isShow()) {
|
||
return
|
||
}
|
||
closeSidebar()
|
||
})
|
||
})
|
||
|
||
function openSidebar() {
|
||
document.body.classList.add('overflow-hidden')
|
||
sidebarElement.classList.remove('hidden')
|
||
}
|
||
|
||
function closeSidebar() {
|
||
sidebarElement.classList.add('hidden')
|
||
document.body.classList.remove('overflow-hidden')
|
||
}
|
||
|
||
function isShow() {
|
||
return !sidebarElement.classList.contains('hidden')
|
||
}
|
||
|
||
function toggleSidebar() {
|
||
if (isShow()) {
|
||
closeSidebar()
|
||
} else {
|
||
openSidebar()
|
||
}
|
||
}</script></body></html> |