allow making encrypted rsync special remotes
wow, that was easy!
This commit is contained in:
parent
5228ba9314
commit
014974a7da
6 changed files with 105 additions and 64 deletions
|
@ -195,25 +195,37 @@ getAddDriveR = bootstrap (Just Config) $ do
|
||||||
hostname <- maybe "host" id <$> liftIO getHostname
|
hostname <- maybe "host" id <$> liftIO getHostname
|
||||||
hostlocation <- fromRepo Git.repoLocation
|
hostlocation <- fromRepo Git.repoLocation
|
||||||
liftIO $ inDir dir $
|
liftIO $ inDir dir $
|
||||||
void $ addRemote' hostname hostlocation
|
void $ makeGitRemote hostname hostlocation
|
||||||
addRemote name dir
|
addRemote $ makeGitRemote name dir
|
||||||
|
|
||||||
{- Adds a remote, if there is not already one with the same location. -}
|
{- Runs an action that returns a name of the remote, and finishes adding it. -}
|
||||||
addRemote :: String -> String -> Annex Remote
|
addRemote :: Annex String -> Annex Remote
|
||||||
addRemote name location = do
|
addRemote a = do
|
||||||
name' <- addRemote' name location
|
name <- a
|
||||||
void $ remoteListRefresh
|
void $ remoteListRefresh
|
||||||
maybe (error "failed to add remote") return =<< Remote.byName (Just name')
|
maybe (error "failed to add remote") return =<< Remote.byName (Just name)
|
||||||
|
|
||||||
addRemote' :: String -> String -> Annex String
|
{- Returns the name of the git remote it created. If there's already a
|
||||||
addRemote' name location = inRepo $ \r ->
|
- remote at the location, returns its name. -}
|
||||||
|
makeGitRemote :: String -> String -> Annex String
|
||||||
|
makeGitRemote basename location = makeRemote basename location $ \name ->
|
||||||
|
void $ inRepo $
|
||||||
|
Git.Command.runBool "remote"
|
||||||
|
[Param "add", Param name, Param location]
|
||||||
|
|
||||||
|
{- If there's not already a remote at the location, adds it using the
|
||||||
|
- action, which is passed the name of the remote to make.
|
||||||
|
-
|
||||||
|
- Returns the name of the remote. -}
|
||||||
|
makeRemote :: String -> String -> (String -> Annex ()) -> Annex String
|
||||||
|
makeRemote basename location a = do
|
||||||
|
r <- fromRepo id
|
||||||
if (null $ filter samelocation $ Git.remotes r)
|
if (null $ filter samelocation $ Git.remotes r)
|
||||||
then do
|
then do
|
||||||
let name' = uniqueRemoteName r name 0
|
let name = uniqueRemoteName r basename 0
|
||||||
void $ Git.Command.runBool "remote"
|
a name
|
||||||
[Param "add", Param name', Param location] r
|
return name
|
||||||
return name'
|
else return basename
|
||||||
else return name
|
|
||||||
where
|
where
|
||||||
samelocation x = Git.repoLocation x == location
|
samelocation x = Git.repoLocation x == location
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,16 @@ import Assistant.WebApp.Types
|
||||||
import Assistant.WebApp.SideBar
|
import Assistant.WebApp.SideBar
|
||||||
import Utility.Yesod
|
import Utility.Yesod
|
||||||
import Assistant.WebApp.Configurators.Local
|
import Assistant.WebApp.Configurators.Local
|
||||||
|
import qualified Types.Remote as R
|
||||||
|
import qualified Remote.Rsync as Rsync
|
||||||
|
import qualified Command.InitRemote
|
||||||
|
import Logs.UUID
|
||||||
|
import Logs.Remote
|
||||||
|
|
||||||
import Yesod
|
import Yesod
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Map as M
|
||||||
import Network.BSD
|
import Network.BSD
|
||||||
import System.Posix.User
|
import System.Posix.User
|
||||||
import System.Process (CreateProcess(..))
|
import System.Process (CreateProcess(..))
|
||||||
|
@ -156,16 +162,6 @@ testServer sshserver = do
|
||||||
report r = "echo " ++ token r
|
report r = "echo " ++ token r
|
||||||
sshopt k v = concat ["-o", k, "=", v]
|
sshopt k v = concat ["-o", k, "=", v]
|
||||||
|
|
||||||
{- ssh://user@host/path -}
|
|
||||||
genSshUrl :: SshData -> Text
|
|
||||||
genSshUrl s = T.concat ["ssh://", u, h, d, "/"]
|
|
||||||
where
|
|
||||||
u = maybe "" (\v -> T.concat [v, "@"]) $ sshUserName s
|
|
||||||
h = sshHostName s
|
|
||||||
d
|
|
||||||
| "/" `T.isPrefixOf` sshDirectory s = d
|
|
||||||
| otherwise = T.concat ["/~/", sshDirectory s]
|
|
||||||
|
|
||||||
{- user@host or host -}
|
{- user@host or host -}
|
||||||
genSshHost :: Text -> Maybe Text -> String
|
genSshHost :: Text -> Maybe Text -> String
|
||||||
genSshHost host user = maybe "" (\v -> T.unpack v ++ "@") user ++ T.unpack host
|
genSshHost host user = maybe "" (\v -> T.unpack v ++ "@") user ++ T.unpack host
|
||||||
|
@ -239,52 +235,75 @@ getConfirmSshR sshdata = sshConfigurator $ do
|
||||||
let haspubkey = isJust $ pubKey sshdata
|
let haspubkey = isJust $ pubKey sshdata
|
||||||
$(widgetFile "configurators/confirmssh")
|
$(widgetFile "configurators/confirmssh")
|
||||||
|
|
||||||
{- Creates the repository on the remote. Does any necessary ssh key setup.
|
getMakeSshGitR :: SshData -> Handler RepHtml
|
||||||
-
|
getMakeSshGitR = makeSsh False
|
||||||
- This is a one-sided remote setup; the remote server probably does not
|
|
||||||
- have a route to the client here.
|
getMakeSshRsyncR :: SshData -> Handler RepHtml
|
||||||
-}
|
getMakeSshRsyncR = makeSsh True
|
||||||
getMakeSshR :: SshData -> Handler RepHtml
|
|
||||||
getMakeSshR sshdata = do
|
makeSsh :: Bool -> SshData -> Handler RepHtml
|
||||||
|
makeSsh rsync sshdata = do
|
||||||
(transcript, ok) <- liftIO $ sshTranscript [sshhost, remoteCommand]
|
(transcript, ok) <- liftIO $ sshTranscript [sshhost, remoteCommand]
|
||||||
if ok
|
if ok
|
||||||
then do
|
then do
|
||||||
r <- runAnnex undefined $
|
r <- runAnnex undefined makerepo
|
||||||
addRemote (sshRepoName sshdata) sshurl
|
|
||||||
syncRemote r
|
syncRemote r
|
||||||
redirect RepositoriesR
|
redirect RepositoriesR
|
||||||
else showerr transcript
|
else showerr transcript
|
||||||
where
|
where
|
||||||
sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata)
|
sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata)
|
||||||
authline = authorizedKeysLine sshdata
|
|
||||||
remotedir = T.unpack $ sshDirectory sshdata
|
remotedir = T.unpack $ sshDirectory sshdata
|
||||||
sshurl = T.unpack $ genSshUrl sshdata
|
|
||||||
remoteCommand = join "&&" $ catMaybes
|
remoteCommand = join "&&" $ catMaybes
|
||||||
[ Just $ "mkdir -p " ++ shellEscape remotedir
|
[ Just $ "mkdir -p " ++ shellEscape remotedir
|
||||||
, Just $ "cd " ++ shellEscape remotedir
|
, Just $ "cd " ++ shellEscape remotedir
|
||||||
, Just $ join "&&" makerepo
|
, if rsync then Nothing else Just $ "git init --bare --shared"
|
||||||
, if null authline
|
, if rsync then Nothing else Just $ "git annex init"
|
||||||
then Nothing
|
, makeAuthorizedKeys sshdata
|
||||||
else Just $ join "&&" makeAuthorizedKeys
|
|
||||||
]
|
|
||||||
makerepo
|
|
||||||
| rsyncOnly sshdata = []
|
|
||||||
| otherwise =
|
|
||||||
[ "git init --bare --shared"
|
|
||||||
, "git annex init"
|
|
||||||
]
|
|
||||||
makeAuthorizedKeys =
|
|
||||||
[ "mkdir -p ~/.ssh"
|
|
||||||
, "touch ~/.ssh/authorized_keys"
|
|
||||||
, "chmod 600 ~/.ssh/authorized_keys"
|
|
||||||
, unwords
|
|
||||||
[ "echo"
|
|
||||||
, shellEscape authline
|
|
||||||
, ">>~/.ssh/authorized_keys"
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
showerr msg = sshConfigurator $
|
showerr msg = sshConfigurator $
|
||||||
$(widgetFile "configurators/makessherror")
|
$(widgetFile "configurators/makessherror")
|
||||||
|
{- This is a one-sided remote setup; the remote server
|
||||||
|
- probably does not have a route to the client here. -}
|
||||||
|
makerepo = addRemote $
|
||||||
|
(if rsync then makeRsyncRemote else makeGitRemote)
|
||||||
|
(sshRepoName sshdata) sshurl
|
||||||
|
sshurl = T.unpack $ T.concat $ if rsync
|
||||||
|
then [u, h, ":", sshDirectory sshdata, "/"]
|
||||||
|
else ["ssh://", u, h, d, "/"]
|
||||||
|
where
|
||||||
|
u = maybe "" (\v -> T.concat [v, "@"]) $ sshUserName sshdata
|
||||||
|
h = sshHostName sshdata
|
||||||
|
d
|
||||||
|
| "/" `T.isPrefixOf` sshDirectory sshdata = d
|
||||||
|
| otherwise = T.concat ["/~/", sshDirectory sshdata]
|
||||||
|
|
||||||
|
{- Inits a rsync special remote, and returns the name of the remote. -}
|
||||||
|
makeRsyncRemote :: String -> String -> Annex String
|
||||||
|
makeRsyncRemote name location = makeRemote name location $ const $ do
|
||||||
|
(u, c) <- Command.InitRemote.findByName name
|
||||||
|
c' <- R.setup Rsync.remote u $ M.union config c
|
||||||
|
describeUUID u name
|
||||||
|
configSet u c'
|
||||||
|
where
|
||||||
|
config = M.fromList
|
||||||
|
[ ("encryption", "shared")
|
||||||
|
, ("rsyncurl", location)
|
||||||
|
, ("type", "rsync")
|
||||||
|
]
|
||||||
|
|
||||||
|
makeAuthorizedKeys :: SshData -> Maybe String
|
||||||
|
makeAuthorizedKeys sshdata
|
||||||
|
| pubKey sshdata == Nothing = Nothing
|
||||||
|
| otherwise = Just $ join "&&" $
|
||||||
|
[ "mkdir -p ~/.ssh"
|
||||||
|
, "touch ~/.ssh/authorized_keys"
|
||||||
|
, "chmod 600 ~/.ssh/authorized_keys"
|
||||||
|
, unwords
|
||||||
|
[ "echo"
|
||||||
|
, shellEscape $ authorizedKeysLine sshdata
|
||||||
|
, ">>~/.ssh/authorized_keys"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
authorizedKeysLine :: SshData -> String
|
authorizedKeysLine :: SshData -> String
|
||||||
authorizedKeysLine sshdata@(SshData { pubKey = Just pubkey })
|
authorizedKeysLine sshdata@(SshData { pubKey = Just pubkey })
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
/config/repository/add/drive AddDriveR GET
|
/config/repository/add/drive AddDriveR GET
|
||||||
/config/repository/add/ssh AddSshR GET
|
/config/repository/add/ssh AddSshR GET
|
||||||
/config/repository/add/ssh/confirm/#SshData ConfirmSshR GET
|
/config/repository/add/ssh/confirm/#SshData ConfirmSshR GET
|
||||||
/config/repository/add/ssh/make/#SshData MakeSshR GET
|
/config/repository/add/ssh/make/git/#SshData MakeSshGitR GET
|
||||||
|
/config/repository/add/ssh/make/rsync/#SshData MakeSshRsyncR GET
|
||||||
/config/repository/first FirstRepositoryR GET
|
/config/repository/first FirstRepositoryR GET
|
||||||
|
|
||||||
/transfers/#NotificationId TransfersR GET
|
/transfers/#NotificationId TransfersR GET
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
<div .span9 .hero-unit>
|
<div .span9 .hero-unit>
|
||||||
<h2>
|
<h2>
|
||||||
Adding a remote server using ssh
|
Adding a remote server using ssh
|
||||||
<p>
|
|
||||||
Clone this repository to a ssh server. Your data will be #
|
|
||||||
uploaded to the server. If you set up other devices to use the same #
|
|
||||||
server, they will all be kept in sync, using the server as a central #
|
|
||||||
hub.
|
|
||||||
<p>
|
<p>
|
||||||
You can use nearly any server that has ssh and rsync. For example, you #
|
You can use nearly any server that has ssh and rsync. For example, you #
|
||||||
could use a <a href="http://linode.com/">Linode</a> or another VPS, or #
|
could use a <a href="http://linode.com/">Linode</a> or another VPS, or #
|
||||||
|
|
|
@ -5,9 +5,23 @@
|
||||||
<div .span8>
|
<div .span8>
|
||||||
<p>
|
<p>
|
||||||
The server has been verified to be usable.
|
The server has been verified to be usable.
|
||||||
|
$if not (rsyncOnly sshdata)
|
||||||
|
<p>
|
||||||
|
You have two options for how to use the server.
|
||||||
|
<p>
|
||||||
|
<a .btn .btn-primary href="@{MakeSshGitR sshdata}" onclick="$('#setupmodal').modal('show');">
|
||||||
|
Use a git repository on the server
|
||||||
|
<br>
|
||||||
|
All your data will be uploaded to the server. If you set up other #
|
||||||
|
devices to use the same server, they will all be kept in sync, #
|
||||||
|
using the server as a central hub. #
|
||||||
<p>
|
<p>
|
||||||
<a .btn .btn-primary href="@{MakeSshR sshdata}" onclick="$('#setupmodal').modal('show');">
|
<a .btn .btn-primary href="@{MakeSshRsyncR sshdata}" onclick="$('#setupmodal').modal('show');">
|
||||||
Clone this repository to the remote server
|
Use an encrypted rsync repository on the server
|
||||||
|
<br>
|
||||||
|
The contents of your files will be stored, fully encrypted, on the #
|
||||||
|
server. The server will not store other information about your #
|
||||||
|
git repository.
|
||||||
<div .span4>
|
<div .span4>
|
||||||
$if haspubkey
|
$if haspubkey
|
||||||
<div .alert .alert-info>
|
<div .alert .alert-info>
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
<p>
|
<p>
|
||||||
Transcript: #{msg}
|
Transcript: #{msg}
|
||||||
<p>
|
<p>
|
||||||
<a .btn .btn-primary href="@{MakeSshR sshdata}">
|
<a .btn .btn-primary href="#">
|
||||||
Retry
|
Retry
|
||||||
|
|
Loading…
Add table
Reference in a new issue